【发布时间】:2019-06-17 23:34:02
【问题描述】:
我正在尝试实现这一点:
制作一个执行以下操作的 C 多进程程序:
一个进程 P 生成两个子进程 P1 和 P2。两个儿子 P1 和 P2 执行一个不确定的循环,其中每秒生成一个介于 0 和 100 之间的随机整数。每次抽奖时,孩子们交流由父 P 进程生成的数字,该进程提供将它们相加,并将它们打印在屏幕并将它们存储在一个文件中。进程 P1 必须处理 SIGINT 中断信号。特别是,在此信号到达时,P1 必须显示警告消息“P1 进程忙!”。当父 P 进程验证它从子进程接收到的数字的总和为 100 时,该程序被父 P 进程终止。
现在,我需要一些帮助来实现孩子和父母之间的同步。我试图使用信号量,但看起来不可能。我可以用什么来同步它们?信号?怎么样?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <semaphore.h>
#include <fcntl.h>
#define READ 0
#define WRITE 1
void handler(int sig){
printf("process 1 is busy\n");
}
void codeprocess1(int pd[], sem_t *sem1){
int i = 0;
int numgenerated;
while( i = 0){
signal(SIGUSR1, handler);
numgenerated = rand()%101;
close(pd[READ]);
write(pd[WRITE], &numgenerated, sizeof(int));
sleep(1);
sem_wait(sem1);
}
}
void codeprocess2(int pd[], sem_t *sem2){
int i = 0;
int numgenerated;
while( i = 0){
numgenerated = rand()%101;
close(pd[READ]);
write(pd[WRITE], &numgenerated, sizeof(int));
sleep(1);
sem_wait(sem2);
}
}
int main(){
pid_t pid1, pid2;
int sum, numread1, numread2, pipe1[2], pipe2[2];
sem_t *sem2 = sem_open("semaph2", O_CREAT | O_EXCL, 1, 0);
sem_t *sem1 = sem_open("semaph1", O_CREAT | O_EXCL, 1, 0);
if(pipe(pipe1)<0){
exit(1);
}
if(pipe(pipe2)<0){
exit(1);
}
pid1 = fork();
switch(pid1){
case -1:
exit(1);
case 0:
codeprocess1(pipe1, sem1);
break;
default:
pid2= fork();
switch( pid2){
case -1:
exit(1);
case 0:
codeprocess2(pipe2, sem2);
break;
default:
while(sum!=1000){
close(pipe1[WRITE]);
read(pipe1[READ], &numread1, sizeof(int));
close(pipe2[WRITE]);
read(pipe2[READ], &numread2, sizeof(int));
sum = sum + numread1 + numread2;
printf("%d\n", sum);
sem_post(sem1);
sem_post(sem2);
}
kill(0, SIGKILL);
}
}
}
【问题讨论】:
-
为什么你认为你需要一些同步?是否有规定轮到对方时P1和P2必须等待?如果没有,您所要做的就是确保 P 在使用之前从 P1 或 P2 读取完整的数字。您可以使用
select找出准备读取的管道。当 P1 和 P2 每秒写入一个整数时,您可能不会注意到任何问题,但您应该为不完整的write或read或信号发生时的错误指示做好准备。您对变量等的命名不一致。请修复编译器错误/警告并更新代码。 -
信号处理存在问题。使用
signal(),信号处理程序可能会在信号发生时重置为默认值。然后第二个SIGINT可能会终止程序。确切的行为取决于库版本、#includes 和预处理器符号。最好使用sigaction。在信号处理程序中调用printf是不好的,因为它不可重入。最好只在处理程序中设置volatile sig_atomic_t类型的变量(或更多),然后检查并重置主循环中的值。如果像read或write这样的系统调用被信号中断,它将返回-1和errno==EINTR。 -
从问题陈述中,我看不出为什么你会使用比管道更复杂的东西来进行通信,并且它们会为你处理同步。
标签: c multiprocess