作为一个练习,我需要在获得信号时使用信号处理程序和管道在两个进程之间发送一些消息。下面是我的源代码。当我运行它时,我可以让管道工作,两个进程都可以对话,只要我在它们的主方法中调用管道(在本例中为process1()和process2())。但我想使用信号处理器内部的管道。但现在管道坏了。这是我得到的一些输出:
3 - 4 and 5 - 6
Segv at 8825
USR1 at 8824
898 sent to 4
130 received on 3
130
"898"one_answers"130"应该相等,但不是。我知道管道工作正常,所以我认为这与信号有关。。。但是什么。。。?
来源代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
int fd1[2], fd2[2], status;
int cpid, cpoid;
void process1() {
cpid = getpid(); /*What's my process ID?*/
cpoid = cpid + 1; /*And what's the other process ID?*/
close(fd1[0]);
close(fd2[1]);
while (1) {}
}
void process2() {
cpid = getpid();
cpoid = cpid - 1;
close(fd1[1]);
close(fd2[0]);
raise(SIGSEGV); /*Start with a SegV signal*/
while (1) {}
}
/*Method to send a message to the other process, by pipe*/
void send (int msg) {
if (cpid < cpoid) {
write(fd1[1], &msg, 1);
printf("%d sent to %dn", msg, fd1[1]);
} else {
write(fd2[1], &msg, 1);
printf("%d sent to %dn", msg, fd2[1]);
}
}
/*Method to receive a message from the other process*/
int receive () {
int msg = 0;
if (cpid < cpoid) {
read(fd2[0], &msg, 1);
printf("%d received on %dn", msg, fd2[0]);
} else {
read(fd1[0], &msg, 1);
printf("%d received on %dn", msg, fd1[0]);
}
return msg;
}
/*The SegV Signal handler*/
void segvHandler() {
int y = -1;
printf("Segv at %dn", cpid);
kill(cpoid, SIGUSR1); /*Send an USR1 Signal to the other proces*/
while (y != 898) {
y = receive();
printf("%dn", y);
}
}
/*The Usr1 Signal handler*/
void usr1Handler() {
int x = 898;
printf("USR1 at %dn", cpid);
send(x);
}
int main (int argc, char *argv[]) {
if (pipe(fd1) < 0) {
fprintf (stderr, "Could not make pipen");
return (EXIT_FAILURE);
}
if (pipe(fd2) < 0) {
fprintf (stderr, "Could not make pipen");
return (EXIT_FAILURE);
}
printf("%d - %d and %d - %dn", fd1[0], fd1[1], fd2[0], fd2[1]); /*Pipe numbers*/
signal(SIGUSR1, usr1Handler); /*Signal handlers*/
signal(SIGSEGV, segvHandler);
if (fork() != 0) {
process1();
} else {
process2();
}
waitpid(-1, &status, 0);
return EXIT_SUCCESS;
}
一些基于快速查看的故障。
-
printf()不是异步信号安全的;不要在信号处理程序中调用它。
-
您正在读取和写入1个字节,很可能小于sizeof(int)。
-
您不能假设PID是连续的。在父级中,fork()的返回值给出子级的PID。在子级中,如果父级在fork()之前存储了getpid()的返回值,那么就有了它;否则请参见getppid()。
正如评论中所提到的,您不应该在信号处理程序中调用printf,但这可能不是问题所在。除非int在您的机器上是一个字节,否则问题是您没有写入或读取整个int,因为您只将一个字节写入管道。(将代码更改为:write(fd[1],&msg,sizeof msg),并对read进行相同的更改。)