为什么我的 C 管道不工作?
作为练习,当收到信号时,我需要使用信号处理程序和管道在两个进程之间发送一些消息。下面是我的源代码。当我运行它时,我可以让管道工作,两个进程都可以通信,只要我在它们的主方法中调用管道(在本例中为 process1() 和 process2() )。 但我想使用信号处理程序内的管道。但现在管道不起作用了。 这是我得到的一些输出:
3 - 4 and 5 - 6
Segv at 8825
USR1 at 8824
898 sent to 4
130 received on 3
130
“898”和“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 %d\n", msg, fd1[1]);
} else {
write(fd2[1], &msg, 1);
printf("%d sent to %d\n", 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 %d\n", msg, fd2[0]);
} else {
read(fd1[0], &msg, 1);
printf("%d received on %d\n", msg, fd1[0]);
}
return msg;
}
/*The SegV Signal handler*/
void segvHandler() {
int y = -1;
printf("Segv at %d\n", cpid);
kill(cpoid, SIGUSR1); /*Send an USR1 Signal to the other proces*/
while (y != 898) {
y = receive();
printf("%d\n", y);
}
}
/*The Usr1 Signal handler*/
void usr1Handler() {
int x = 898;
printf("USR1 at %d\n", cpid);
send(x);
}
int main (int argc, char *argv[]) {
if (pipe(fd1) < 0) {
fprintf (stderr, "Could not make pipe\n");
return (EXIT_FAILURE);
}
if (pipe(fd2) < 0) {
fprintf (stderr, "Could not make pipe\n");
return (EXIT_FAILURE);
}
printf("%d - %d and %d - %d\n", 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;
}
as an exercise I need to use a signal handler, and pipes to send some messages between two processes, when getting a signal. Below is my sourcecode. When I'm running it, I can get the pipes to work, both processes can talk, as long as I call the pipe in their main-method (in this case process1() and process2() ).
But I want to use the pipes inside the signalhandlers. But now the pipes don't work.
This is some output I got:
3 - 4 and 5 - 6
Segv at 8825
USR1 at 8824
898 sent to 4
130 received on 3
130
The '898' and '130' should be equal, but aren't.
I know the pipes are working correctly, so I think it has something to do with the signalstuff...
But what...?
Sourcecode:
#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 %d\n", msg, fd1[1]);
} else {
write(fd2[1], &msg, 1);
printf("%d sent to %d\n", 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 %d\n", msg, fd2[0]);
} else {
read(fd1[0], &msg, 1);
printf("%d received on %d\n", msg, fd1[0]);
}
return msg;
}
/*The SegV Signal handler*/
void segvHandler() {
int y = -1;
printf("Segv at %d\n", cpid);
kill(cpoid, SIGUSR1); /*Send an USR1 Signal to the other proces*/
while (y != 898) {
y = receive();
printf("%d\n", y);
}
}
/*The Usr1 Signal handler*/
void usr1Handler() {
int x = 898;
printf("USR1 at %d\n", cpid);
send(x);
}
int main (int argc, char *argv[]) {
if (pipe(fd1) < 0) {
fprintf (stderr, "Could not make pipe\n");
return (EXIT_FAILURE);
}
if (pipe(fd2) < 0) {
fprintf (stderr, "Could not make pipe\n");
return (EXIT_FAILURE);
}
printf("%d - %d and %d - %d\n", 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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一些错误基于快速查看。
printf() 不是异步信号安全的;不要在信号处理程序中调用它。
您正在读取和写入 1 个字节,这很可能小于 sizeof(int)。
您不能假设 PID 是连续的。在父进程中,fork()的返回值给出了子进程的PID。在子进程中,如果父进程在 fork() 之前存储了 getpid() 的返回值,那么就可以了;否则请参见 getppid()。
Some faults based on a quick look.
printf() is not async-signal-safe; don't call it in a signal handler.
You're reading and writing 1 byte, which is most likely less than sizeof(int).
You cannot assume that PID's are consecutive. In the parent, the return value of fork() gives the PID of the child. In the child, if the parent stored the return value of getpid() before fork(), there you have it; otherwise see getppid().
正如评论中提到的,你不应该
在信号处理程序中调用 printf,但这可能不是问题所在。除非 int 在你的机器上是一个字节,否则问题是你没有写入或读取整个 int,因为你只将一个字节写入管道。 (将代码更改为: write( fd[ 1 ], &msg, sizeof msg ) 并对读取进行相同的更改。)
As mentioned in the comments, you should not
invoke printf in a signal handler, but that is probably not the problem. Unless ints are one byte on your machine, the issue is that you are not writing or reading the whole int, since you only write one byte into the pipe. (Change the code to: write( fd[ 1 ], &msg, sizeof msg ) and make the same change on the read.)