我有一个以复杂的方式实现生产者消费者问题的任务(可能是为了测试我的理解)。父进程应该设置共享内存。应该初始化未命名的信号量(用于空计数和填充计数),并且应该初始化互斥锁。然后创建两个子进程,生成器子进程和消费者子进程。每个子进程都应该创建一个应该完成这项工作的新线程。
PS:我已经读过,信号量应保存在共享内存中,因为它们将由不同的进程共享。
请提供一些提示或建议更改。
到目前为止,我已经这样做了:
struct shmarea
{
unsigned short int read;
unsigned short int max_size;
char scratch[3][50];
unsigned short int write;
sem_t sem1;// Empty slot semaphore
sem_t sem2;// Filled slot Semaphore
};
void *thread_read(void* args);
void *thread_write(void *args);
pthread_mutex_t work_mutex;
struct shmarea *shma;
int main()
{
int fork_value,i=0,shmid;
printf("Parent process id is %d\n\n",getpid());
int res1,res2;
key_t key;
char *path = "/tmp";
int id = 'S';
key = ftok(path, id);
shmid = shmget(key,getpagesize(),IPC_CREAT|0666);
printf("Parent:Shared Memory id = %d\n",id);
shma = shmat(shmid,0,0);
shma->read = 0;
shma->max_size = 3;
shma->write = 0;
pthread_t a_thread;
pthread_t b_thread;
void *thread_result1,*thread_result2;
res1 = sem_init(&(shma->sem1),1,3);//Initializing empty slot sempahore
res2 = sem_init(&(shma->sem2),1,0);//Initializing filled slot sempahore
res1 = pthread_mutex_init(&work_mutex,NULL);
while(i<2)
{
fork_value = fork();
if(fork_value > 0)
{
i++;
}
if(fork_value == 0)
{
if(i==0)
{
printf("***0***\n");
//sem_t sem1temp = shma->sem1;
char ch;int res;
res= pthread_create(&a_thread,NULL,thread_write,NULL);
}
if(i==1)
{
printf("***1***\n");
//sem_t sem2temp = shma->sem2;
int res;
char ch;
res= pthread_create(&b_thread,NULL,thread_read,NULL);
}
}
}
int wait_V,status;
res1 = pthread_join(a_thread,&thread_result1);
res2 = pthread_join(b_thread,&thread_result2);
}
void *thread_read(void *args)
{
while(1)
{
sem_wait(&(shma->sem2));
pthread_mutex_lock(&work_mutex);
printf("The buf read from consumer:%s\n",shma->scratch[shma->read]);
shma->read = (shma->read+1)%shma->max_size;
pthread_mutex_unlock(&work_mutex);
sem_post(&(shma->sem1));
}
}
void *thread_write(void *args)
{
char buf[50];
while(1)
{
sem_wait(&(shma->sem1));
pthread_mutex_lock(&work_mutex);
read(STDIN_FILENO,buf,sizeof(buf));
strcpy(shma->scratch[shma->write],buf);
shma->write = (shma->write+1)%shma->max_size;
pthread_mutex_unlock(&work_mutex);
sem_post(&(shma->sem2));
}
}
答案 0 :(得分:1)
(1)到目前为止,你最大的问题是你已经设法写了一个叉炸弹。因为你没有退出fork循环中的任何一个子节点,所以每个子节点都会通过并循环并创建自己的子节点,直到崩溃或使系统关闭。你想要更像这样的东西:
while(i < 2)
{
fork_value = fork();
if(fork_value > 0)
i++;
if(fork_value == 0)
{
if(i==0)
{
printf("0 child is pid %d\n", getpid());
int res;
res = pthread_create(&a_thread,NULL,thread_write,NULL);
res = pthread_join(a_thread,&thread_result1);
exit(0);
}
if(i==1)
{
printf("1 child is pid %d\n", getpid());
int res;
res = pthread_create(&b_thread,NULL,thread_read,NULL);
res = pthread_join(b_thread,&thread_result2);
exit(0);
}
}
}
for (i = 0; i < 2; ++i)
wait(NULL);
注意你忽略的孩子的wait
。
(2)始终检查您的退货代码。它们就像安全带,有点拖累但是当你崩溃时非常有帮助。 (是的,我没有在这里听取我的意见,但你应该这样做。)
(3)这些名字很糟糕。
unsigned short int read;
unsigned short int write;
在系统调用后远离命名变量。这令人困惑,只是在寻找麻烦。
(4)术语明智,与这些共同祖先的过程是相关的。父级可以打开共享内存和其他资源,并将其传递给子级。例如,不相关的过程将是从不同终端发起的多个程序实例。他们可以共享资源,但不能以分叉流程的“继承”方式共享资源。
现在已经很晚了,并没有到处看看你正在做什么线程等等,但这应该让你开始。