0
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>

int sleepval = 10, read_num = 0;
int readcnt = 0, writecnt = 0;
pthread_mutex_t mutex;
sem_t rw_mutex;

int randomGenerator(int high, int low){
    srand(time(0));
    return((rand() % (high - low + 1)) + 100);
}

void *reader(void *readno){
    pthread_mutex_lock(&mutex);
    read_num++;
    /* Block the writer if this is the first reader */
    if(read_num == 1){
        sem_wait(&rw_mutex);
    }
    pthread_mutex_unlock(&mutex);
    /* Read sleepval value and print */
    printf("Reader %03d reads %d\n", *((int *)readno), sleepval);
    readcnt++;
    sleep(sleepval / 1000);
    pthread_mutex_lock(&mutex);
    read_num--;
    /*Wake up writer if this is the last reader */
    if(read_num == 0){
        sem_post(&rw_mutex);
    }
    pthread_mutex_unlock(&mutex);
    int num = randomGenerator(500, 100);
    sleep(num / 1000);
}

void *writer(void *writeno){
    int num = randomGenerator(1000, 100);
    sleep(num / 1000);
    num = randomGenerator(50, 10);
    sem_wait(&rw_mutex);
    sleepval = num;
    printf("Writer %02d writes &d\n", *((int*)writeno), sleepval);
    writecnt++;
    sleep(sleepval / 1000);
    sem_post(&rw_mutex);
}

int main(int argc, char *argv[]){
    int r = atoi(argv[1]);
    int w = atoi(argv[2]);
    int second = 0;
    int i, id[100];
    if(r < 1 || r > 100 || w < 1 || w > 10){
        fprintf(stderr, "Usage: readwrite [read](1 - 100) [write](1 - 10)\n");
        exit(-1);
    }
    
    pthread_t read[100], write[10];
    pthread_mutex_init(&mutex, NULL);
    sem_init(&rw_mutex, 0 , 1);

    /* Create threads for readers */
    for(i = 0; i < r; i++){
        id[i] = i;
        pthread_create(&read[i], NULL, (void *)reader, (void *)&id[i]);
    }
    /* Create threads for writers */
    for(i = 0; i < w; i++){
        id[i] = i;
        pthread_create(&write[i], NULL, (void *)writer, (void *)&id[i]);
    }

    sleep(30); //wait for 30 seconds

    /* Signal threads to finish */
    for (i = 0; i < r; i++){
        pthread_join(read[i], NULL);
    }
    for (i = 0; i < w; i++){
        pthread_join(write[i], NULL);
    }

    /* Display number of occurred reads and writes */
    printf("\n==============================\n");
    printf("Number of reads  :\t%03d\n", readcnt);
    printf("Number of writes :\t%03d\n", writecnt);

    pthread_mutex_destroy(&mutex);
    sem_destroy(&rw_mutex);

    return 0;
}

这个作业是关于解决第一个读写器问题。我可以使用 gcc -lpthread -lrt 在 linux 中编译它。但是当我尝试使用给定的格式 readwrtie 100 10 运行它时,我得到了分段错误(核心转储),我不知道为什么。我尝试使用 valgrind a.out 运行以查看问题,但我无法理解。请帮我。

Memcheck,内存错误检测器

==19787== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.

==19787== 使用 Valgrind-3.8.1 和 LibVEX;使用 -h 重新运行以获取版权信息

==19787== 命令:a.out

==19787==

==19787== 大小为 1 的读取无效

==19787== 在 0x57E7AC:____strtol_l_internal(在 /lib/libc-2.12.so 中)

==19787== 由 0x57E50F:strtol(在 /lib/libc-2.12.so 中)

==19787== by 0x57AEB0: atoi (in /lib/libc-2.12.so)

==19787== by 0x8048A32: main (in /gaia/class/student/maih/maih-asgmt3/a.out)

==19787== 地址 0x0 没有被堆栈、malloc 或(最近)释放

==19787==

==19787==

==19787== 进程以信号 11 (SIGSEGV) 的默认操作终止

==19787== 访问不在地址 0x0 的映射区域内

==19787== 在 0x57E7AC:____strtol_l_internal(在 /lib/libc-2.12.so 中)

==19787== 由 0x57E50F:strtol(在 /lib/libc-2.12.so 中)

==19787== by 0x57AEB0: atoi (in /lib/libc-2.12.so)

==19787== by 0x8048A32: main (in /gaia/class/student/maih/maih-asgmt3/a.out)

==19787== 如果您认为这是由于堆栈造成的

==19787== 程序主线程溢出(不太可能但

==19787==可能),你可以尝试增加大小

==19787== 使用 --main-stacksize= 标志的主线程堆栈。

==19787== 本次运行使用的主线程堆栈大小为 10485760。

==19787==

==19787== 堆摘要:

==19787== 在退出时使用:0 个块中的 0 个字节

==19787== 总堆使用量:0 分配,0 释放,0 字节分配

==19787==

==19787== 所有堆块都被释放——不可能有泄漏

==19787==

==19787== 对于检测到和抑制的错误计数,重新运行:-v

==19787== 错误摘要:1 个上下文中的 1 个错误(抑制:8 个中的 13 个)

分段错误(核心转储)

4

1 回答 1

0

在您的 writer 功能中,更改

printf("Writer %02d writes &d\n", *((int*)writeno), sleepval);
---------------------------^

printf("Writer %02d writes %d\n", *((int*)writeno), sleepval);
---------------------------^

在您的主要功能中,更改

pthread_create(&read[i], NULL, (void *)reader, (void *)&id[i]);
pthread_create(&write[i], NULL, (void *)writer, (void *)&id[i]);

pthread_create(&read[i], NULL, reader, &id[i]);
pthread_create(&write[i], NULL, writer, &id[i]);

向 reader 和 writer 函数添加 return 语句。删除 main 函数中未使用的变量 second。

再试一次。

于 2020-11-18T08:36:24.833 回答