这里是代码,其中父进程在管道中写入字符串输入,子进程从管道中读取字符串输入。如果子进程从管道中读取单词“ end”,那么我想终止所有进程,然后自行终止,如果读取了“ finish”这个单词,我想向父亲发出信号,要求杀死所有进程,然后退出。我运行代码,但出现了段错误。为什么错了?
#define _POSIX_SOURCE
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
void measure_time(int sig)
{
printf("child [%d] received signal %d\n", getpid(), sig);
}
int main(int argc, char *argv[])
{
int n_task = 4;
pid_t pid;
pid_t pid_array[n_task];
int fd[2];
for (int i = 0; i < n_task; i++)
{
pid = fork();
if (pipe(fd) == -1)
{
perror(" pipe ");
exit(1);
}
if (pid < 0)
{
perror("fork");
exit(1);
}
if (pid == 0) //child
{
char *buf;
close(fd[1]);
read(fd[0], buf, 10);
printf("I read: %s", buf);
if (strcmp(buf, "end") == 0)
{
for (int i = 0; i < n_task; i++)
kill(pid_array[i], SIGUSR1);
}else if(strcmp(buf,"finish") == 0){
/*Here i want father to kill all children and then exit.*/
}
exit(0);
}
close(fd[0]);
char *buf;
printf("Give the input string: \n");
scanf("%s", buf);
write(fd[1], buf, strlen(buf));
close(fd[1]);
pid_array[i] = pid;
}
sleep(1);
for (int i = 0; i < n_task; i++)
wait(NULL);
return (0);
}
您正在声明指针buf
,但未初始化它。由于指针无效,随后对read()
和scanf()
的调用将失败。
您需要确保buf
已初始化并指向有效内存。修复代码的一种简单方法是:
char buf[10];
read(fd[0], buf, 10);
如果使用-Wall
启用编译器警告,则编译器将警告您有关初始化变量。
请注意潜在的缓冲区溢出:如果声明char buf[10]
,请确保不会向其中写入超过10个字节。另外,请检查read()
,write()
,scanf()
之类的函数的返回值,以确保没有遇到错误,否则缓冲区或输出文件的内容可能与预期的不一样。
除了由@G标识的未初始化buf
的问题。 Sliepen,需要在pipe()
之前调用fork()
,因为在派生子进程时文件描述符保持打开状态。这也是管道的工作方式。
您可以尝试更改代码段,将pipe()
放在fork()
之前。
...
if (pipe(fd) == -1)
{
perror(" pipe ");
exit(1);
}
pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);
}
...
请阅读pipe(2)的手册页。