从管道读取的信号发送 [英] Reading from pipe on signal sending

查看:156
本文介绍了从管道读取的信号发送的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想:

父进程:


  • 将数据写入到管道

  • 发送信号给子进程

子进程:


  • 信号被捕获后,读取数据。

下面是我试用:

#include<stdio.h>
#include<string.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <unistd.h> 
#include <signal.h>

int fd[2];   


//Handler - Exiting process, OR reading from pipe
void sigHandler(int signumber){

   if(signumber == SIGUSR1) {

    printf("SIGUSR1 catched.\n");


    //So lets read from pipe
    int read_data = -1;
    close(fd[1]);
    read(fd[0], &read_data, sizeof(read_data));

    //This printf never gets called
    printf("Received data: %s", read_data);


   }
   else  {

   printf("SIGQUIT catched.\n");
    exit(3);
   }
}

//This is handles parent process to NOT exit on sending a signal
//maybe not the best workaround but i could only do this in this way.
void sigDummy(int signumber){
    printf("SigDummy catched\n");
}


int main(){    

fflush(stdout);

pipe(fd);
char option=-1;

pid_t child_a;
pid_t child_b;

child_a = fork();

//A Child Proc which is not used atm, it will be
if (child_a == 0) {

    signal(SIGQUIT ,sigHandler); 
    signal(SIGUSR1 ,sigHandler); 

    while(1) {
      //idle    
        sleep(1);
        printf("child_a iddle work\n");

    }


} 

    //Child B Proc for reading form the PIPE after got SIGUSR1 signal
    else {
    child_b = fork();

    if (child_b == 0) {

        signal(SIGQUIT ,sigHandler); 
        signal(SIGUSR1 ,sigHandler); 

        while(1) {
        //idle
            sleep(1);
            printf("child_b iddle work\n");

        }

    } 
    //Parent Proc for writing to a pipe and sending signals to child B to read the pipe
    else {

            signal(SIGUSR1 ,sigDummy); 

            //MENU WHILE
            while(option!=0){

                scanf("%d", &option);
                printf("input was: %d\n", option);
                kill(child_b,SIGUSR1); 

                close(fd[0]);
                write(fd[1], &option, sizeof(option));
            }

        }//End of Menu while

        //Exiting child prcoesses then exiting parent prcoess
        if(option==0){

            int status_a, status_b;

            waitpid(child_b, &status_b, WNOHANG|WUNTRACED);
            waitpid(child_a, &status_a, WNOHANG|WUNTRACED);

            kill(child_b,SIGQUIT); 
            kill(child_a,SIGQUIT); 

        }

    }

    return 1;

} 

输出:

child_b iddle work
child_a iddle work
child_b iddle work
child_a iddle work
child_b iddle work
child_a iddle work
child_b iddle work
child_a iddle work
4
input was: 4
SigDummy catched
SIGUSR1 catched.
SIGUSR1 catched. //I wait here several seconds, child_a and b processes are not printing anything anymore....
3
input was: 3
SigDummy catched
1
input was: 1
SigDummy catched

如果我疏通管道写管道阅读部分我有很好的工作code:

And if i remove the pipe writing the pipe reading parts i have nice working code:

无管输出写入和读:

child_a iddle work
child_b iddle work
3
input was: 3
SigDummy catched
SIGUSR1 catched.
child_a iddle work
SIGUSR1 catched.
child_b iddle work
child_a iddle work
child_b iddle work
2
input was: 2
SigDummy catched
SIGUSR1 catched.
child_b iddle work
SIGUSR1 catched.
child_a iddle work
child_b iddle work
child_a iddle work
1
input was: 1
SigDummy catched
SIGUSR1 catched.
child_b iddle work
SIGUSR1 catched.
child_a iddle work
child_b iddle work
child_a iddle work
4
input was: 4  //Inputs are always catched with my signal handler func, and child processes does not stop printing.
SigDummy catched
SIGUSR1 catched.
child_b iddle work
SIGUSR1 catched.
child_a iddle work
child_b iddle work
child_a iddle work
child_b iddle work
child_a iddle work
0
input was: 0
SigDummy catched
SIGUSR1 catched.
SIGQUIT catched.
SIGUSR1 catched.
SIGQUIT catched.
Exiting

我发现了方法,而不写读管道部分运作良好。但添加后简直是随机错误的。

The method i found out is working well without the write-read pipe part. But after adding it it is simply randomly wrong.

那么,为什么我的code行为,当我尝试做管道发送的事情其他办法吗?我刚开始学C,和code可真的搞砸了,是不错的吧。

So why my code behaviours other way when i try to do the pipe sending thing? I just started to learn c, and the code may be really messed up, be nice please.

推荐答案

的问题是的printf(接收到的数据:%S的read_data); 语句。通过将%S 在格式字符串中,的read_data 变量被视为指针并取消引用(你可能想%d个代替或类似)。

The problem is the printf("Received data: %s", read_data); statement. By putting %s in the format string, the read_data variable is being treated as a pointer and dereferenced (you probably wanted %d instead or similar).

当你把 4 的值。你最终试图访问地址 0xffffff04 这通常会导致分段错误,但在信号处理的情况下,它似乎只是默默地杀子进程。

When you put in a value of 4. You end up trying to access address 0xffffff04 which ordinarily would cause a segmentation fault, but in the context of a signal handler, it just seems to kill the child process silently.

一些其他的东西:


  • 您不应该关闭文件不止一次。文件描述符数量可能在其他地方重复使用,你甚至可能在不经意间亲密的东西你没有预料到。

  • You shouldn't close a file more than once. The file descriptor number may be re-used elsewhere and you might even inadvertently close something you didn't expect to.

要小心你正在写的数据进行读取。你写一个字符大小的一块内存,但读入一个int。确保这就是你真正想要的,否则你会得到意想不到的价值。

Be careful about the data you're writing and reading. You're writing a char sized piece of memory, but reading into an int. Make sure that's what you actually want or you'll get unexpected values.

一般情况下,信号处理程序不是一个伟大的地方做大量繁重的工作。很多操作不在这里很安全,可以当它在意想不到的方式被中断的程序在做什么干扰。它通常是更好地使用信号处理程序简单地通知你的程序的其余部分的东西需要注意,并有主程序做的大部分工作。

Generally, signal handlers aren't a great place to do lots of heavy work. A lot of operations aren't very safe here and can interfere with what the program was doing when it was interrupted in unexpected ways. It's usually better to use the signal handler to simply inform the rest of your program that something needs attention, and have the main program do the majority of the work.

甚至比使用,当你在处理文件中的信号更好,可以使用轮询(同步)或选择()调用(或者,如果你的code是非常简单,只需用文件块阅读()...您的例子code被重新分解完全去除信号处理程序,仍然以同样的方式,但你真正的code可能比这个更复杂​​)。

Even better than using signals when you're dealing with files, you can synchronise with poll() or select() calls (or if your code is simple enough, just block on the file with the read()... your example code be re-factored to remove the signal handlers entirely and still work the same way, but your real code might be more complex than this).

这篇关于从管道读取的信号发送的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆