【发布时间】:2017-05-23 17:59:36
【问题描述】:
我有一个父进程在循环中使用 fork 创建了 16 个子进程。最终,每个子进程都会发送一个 SIGUSR1 信号,该信号由父进程中的处理函数处理。
我的问题是——一些孩子在处理来自另一个孩子的信号时发送信号。我读到处理函数然后停止并处理新信号,忽略它正在处理的当前信号。
我试图通过在处理函数的开头发送:kill(0,SIGSTOP) 来解决这个问题,但看起来这也会停止父进程。有没有办法只向孩子发送这个信号?
如果不可能,使用wait, waitpid and kill 可以实现我的目标吗?
添加了下面的代码,我省略了检查读取、打开等的返回值等内容。
处理函数:
void my_signal_handler( int signum, siginfo_t* info, void* ptr)
{
kill(0, SIGSTOP);
int sonPid = info->si_pid;
char* pipeName = malloc(14 + sizeof(int));//TODO ok?
sprintf(pipeName, "//tmp//counter_%d" , (int) sonPid); //TODO double //?
size_t fdPipe = open(pipeName, O_RDONLY);
int cRead;
int countRead = read(fdPipe,&cRead,sizeof(int));
COUNT+= cRead;
kill(0, SIGCONT);
return;
}
创建子进程:
struct sigaction new_action;
memset(&new_action, 0, sizeof(new_action));
new_action.sa_handler = my_signal_handler;
new_action.sa_flags = SA_SIGINFO;
if( 0 != sigaction(SIGUSR1, &new_action, NULL) )
{
printf("Signal handle registration failed. %s\n", strerror(errno));
return -1;
}
for(int i=0; i<16; i++){
pid_t cpid = fork();
if(cpid == 0) // child
{
execv("./counter",argvv); // some arguments to the function
printf("execv failed: %s\n", strerror(errno));
return -1;
}
else{
continue;
}
孩子们的计数器程序,简而言之,它计算文件某些部分中字符counc的出现,然后将其打印到管道中。:
int main(int argc, char** argv){
int counter = 0;
char counc = argv[1][0];
char* filename = argv[2];
off_t offset = atoll(argv[3]);
ssize_t length = atoll(argv[4]);
int fd = open(filename, O_RDWR | O_CREAT);
char* arr = (char*)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
for(int i=0; i<length; i++){
if(arr[i] == counc){
counter++;
}
}
pid_t proid = getpid();
pid_t ppid = getppid();
char* pipeName = malloc(14 + sizeof(pid_t));
sprintf(pipeName, "//tmp//counter_%d" , (int) proid);
size_t fdPipe = mkfifo(pipeName, 0777);
int didopen = open(pipeName,O_WRONLY);
size_t wrote = write(fdPipe,&counter , 1 );
if(wrote < 0){
printf(OP_ERR, strerror( errno ));
return errno;
}
kill(ppid, SIGUSR1);
//close the pipe and unmap the array
return 1;
}
【问题讨论】:
-
请将您的代码发布为正确的Minimal, Complete, and Verifiable example(请仔细阅读页面)。
-
我认为在这种情况下可以进行解释,但我很快会添加一个代码示例。
-
这不是真的,正在处理的信号被阻塞直到处理程序完成,所以如果它们都发送相同的信号,你应该没问题。一些代码将有助于识别您的真正问题。顺便说一句,保持处理程序简短,只设置标志并在信号处理程序之外进行复杂处理。
-
了解信号安全功能。您的处理程序调用 other 函数。理想情况下,只需将
volatile sig_atomic_t变量设置为主代码的标志,并在处理程序之外执行任何其他操作。 -
@FelixPalmen 我试过了,我得出的结论是我必须在处理程序中使用 sprintf 来获取管道的名称。除非管道在处理程序中打开,否则我认为孩子不能写入它。
标签: c multiprocessing signals handler