c - 在 Linux 中从父进程向子进程发送信号
问题描述
我将很快写下我想用我的代码做什么以及真正的输出是什么。我有一个创建两个子进程的父进程。这两个进程中的每一个都从不同的文件中读取 100 个字节,子 1 从“child1.txt”读取,子 2 从“child2.txt”读取。我想通过使用信号强制在孩子 1 之前执行孩子 2。
我创建了两个子进程并暂停了它们(当它们收到信号时暂停结束)。所以我向孩子 2 发送了一个信号,然后我向孩子 1 发送了一个信号。这样我希望他们会做我想做的事,但他们不会(它总是显示 child1.txt 内容)而且我不明白为什么。
这是代码
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <fcntl.h>
#include <wait.h>
void my_handler(int signo);
int main(int argc, char *argv[]){
signal(SIGCHLD,my_handler);
pid_t pid[2]; //here is where I save child pid
char buffer[100];
for (int i=0;i<2;i++){
if((pid[i]=fork())==0){
signal(SIGUSR1,my_handler);
int fd,nbyte;
pause();
if(i==0){
fd=open("Child1.txt",O_RDONLY);
}else{
fd=open("Child2.txt",O_RDONLY);
}
nbyte=read(fd,buffer,100);
buffer[nbyte-1]='\0';
write(STDOUT_FILENO,buffer,strlen(buffer));
exit(1);
}
sprintf(buffer,"Child %d\n",(int)pid[i]);
write(STDOUT_FILENO,buffer,strlen(buffer));
}
kill(pid[1],SIGUSR1); //I send a signal to unpause child2
wait(NULL); // wait child 2 to terminate
kill(pid[0],SIGUSR1); //unpause child 1
wait(NULL); // wait child 1 to terminate
}
void my_handler(int signo){
}
解决方案
以下建议的代码:
- 干净地编译
- 执行所需的功能
- 正确检查错误
- 使用正确的变量类型
- 通过给它们赋予有意义的名称来消除“神奇”数字
现在建议的代码:
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <fcntl.h>
#include <wait.h>
#define BUF_SIZE 100
#define NUM_CHILDREN 2
void my_handler(int signo);
int main( void )
{
//signal(SIGCHLD,my_handler);
pid_t pid[ NUM_CHILDREN ] = {0};
char buffer[ BUF_SIZE +1];
for ( int i=0; i<NUM_CHILDREN; i++ )
{
if((pid[i]=fork())==0)
{ // then child
signal(SIGUSR1,my_handler);
int fd;
ssize_t nbyte;
pause();
if(i==0)
{
if( (fd=open("child1.txt",O_RDONLY) ) == -1 )
{
perror( "open to read child1.txt failed" );
exit( EXIT_FAILURE );
}
}
else
{
if( (fd=open("child2.txt",O_RDONLY) ) == -1 )
{
perror( "open to read child2.txt failed" );
exit( EXIT_FAILURE );
}
}
if( (nbyte=read(fd,buffer,100) ) ==-1 || nbyte == 0 )
{
perror( "read failed" );
exit( EXIT_FAILURE );
}
buffer[nbyte]='\0';
write(STDOUT_FILENO,buffer,strlen(buffer));
fflush( stdout );
close( fd );
exit( EXIT_SUCCESS );
}
else if( pid[i] > 0 )
{ // then parent
sprintf( buffer,"Child %d PID %d\n", i, (int)pid[i] );
write( STDOUT_FILENO, buffer, strlen(buffer) );
fflush( stdout );
}
else
{ // fork failed
perror( "fork failed" );
}
}
sleep(1); // allow all child processes to be ready for signal
if( pid[0] > 0 )
{
kill(pid[0],SIGUSR1); //send a signal to unpause child 0
wait( NULL );
}
if( pid[1] > 0 )
{
kill(pid[1],SIGUSR1); //unpause child 1
wait( NULL );
}
}
void my_handler(int signo)
{
(void)signo;
}
child1.txt 的内容(注意我使用全小写的文件名)
123
child2.txt 的内容(注意我使用全小写的文件名)
456
运行代码会导致:
Child 0 6630
Child 1 6631
123
456
推荐阅读
- javascript - 如何在javascript中使用数组格式的json数据更新作为变量传递的json键?
- agora.io - Agora.io 安全令牌生成无效(Golang)
- laravel - Laravel 7 - 这条路线在这里很完美,但没有返回视图
- html - 删除行之间的边距
- axapta - 使用外部连接表保存表单要求填写外部表的必填字段
- regex - 是否可以在 Fluent Bit 中为同一输入编写多个正则表达式?
- javascript - 如何使用 jquery 读取 csv 文件并将数据打印到数组中
- django - Amazon Linux 2 AMI 上的命令 01_migrate 失败
- java - 通过 gmail 附件查看 HTML 文件
- cypress - 如何在 cypress 中为 oauth2 google 登录执行 e2e 测试?