C 如何不断重复地从父进程向子进程发送信号?

C 如何不断重复地从父进程向子进程发送信号?,c,signals,fork,parent-child,ipc,C,Signals,Fork,Parent Child,Ipc,我试图得到一个程序来创建n个子进程来读取一个文件,父进程不断地在它们上面循环,并试图发送一个信号来继续读取文件,如果这个进程是空闲的。否则,如果该进程被占用,它将移动到下一个进程。这是我使用信号的方法,但输出是意外的。如果我使用printf调试父级while循环中的代码,我只得到printf语句本身。为什么会这样 据我所知,预期的输出应该是所有n个子进程几乎同时从文件中读取该文件,而该文件很小,然后在再次发生这种情况之前间隔1秒。这是正确的,还是因为比赛条件而不确定 我知道可能有更好的方法使用管

我试图得到一个程序来创建n个子进程来读取一个文件,父进程不断地在它们上面循环,并试图发送一个信号来继续读取文件,如果这个进程是空闲的。否则,如果该进程被占用,它将移动到下一个进程。这是我使用信号的方法,但输出是意外的。如果我使用printf调试父级while循环中的代码,我只得到printf语句本身。为什么会这样

据我所知,预期的输出应该是所有n个子进程几乎同时从文件中读取该文件,而该文件很小,然后在再次发生这种情况之前间隔1秒。这是正确的,还是因为比赛条件而不确定

我知道可能有更好的方法使用管道,但这可以通过信号实现吗?提前谢谢

我知道,正如手册页中提到的,信号的使用不如sigaction那么多,但这能解决吗

printf导致的意外输出是否可能是由于printf本身与IPC的干扰

编辑:用于测试的粘贴箱链接:

包括 包括 包括 包括 包括 包括 包括 int计数器=0; int-fd; 常量字符*文件名; int j=0; int无子女; 国际*消费物价指数; //用户定义信号处理器 静态无效信号; 静态void sig_usr2int signo、siginfo_t*info、void*上下文; 静态无效信号 { //现在,子进程等待读取文件名 //阻塞SIGUSR1,直到完成 信号SIGUSR1,信号; PrintFB现在已锁定。\n; printfChild no%d正在读取。\n\n,getpid; fd=openfilename,O|u RDONLY | O|u CREAT; char buf='a'; int k=0; char*op=char*malloc 255*sizeofchar; 当读取fd和buf时,1 { 如果buf=='\n' { op[k]='\0'; 打破 } 其他的 { op[k++]=buf; } } //现在等待一秒钟,然后发送一个信号 睡眠1; //通过op打印缓冲区的内容 打印输出:%s\n\n,op; //现在打开信号 killgetppid,SIGUSR2; 信号SIGUSR1,sig_usr1; PrintFun现在被阻止\n; } 静态void sig_usr2int sigo,siginfo_t*info,void*context { 如果signo==SIGUSR2 { 子pid=info->si\U pid; printfParent未收到SIGUSR2。PID为%d的子进程现在是空闲的\n\n,子进程\u PID; } } int main argc,char*argv[] { //Filename是第一个参数 filename=argv[1]; //要生成的子进程数 无子女=atoiargv[2]; cpid=int*malloc无子项数*sizeofint; //为SIGUSR2创建sigaction处理程序 struct-sigaction-sa; sa.sa_flags=sa_SIGINFO; sa.sa_sigaction=sig_usr2; sigactionSIGUSR2,&sa,NULL; //不创建子项的子项 forint i=0;我取消注释这一行只打印这条语句。为什么会发生这种情况? killfpid,SIGUSR1; j=j如果我取消对此行的注释,则无法按预期工作。我希望在PID之间切换并向所有PID发送信号 } 返回0; } 样本输出: 注意:这不是一个答案,只是一些经过编辑的代码和可能导致解决方案的结论

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<signal.h>
#include<fcntl.h>
#include<sys/wait.h>

int counter = 0;
int fd;
const char* filename;
int j = 0;
int no_of_children;
int* cpid;
int my_pid;

//User define signal handler
static void sig_usr1(int);
static void sig_usr2(int);

static void sig_usr1(int signo)
{
    //Now the child process waits for reading the Filename

    //Block SIGUSR1 until it's complete
    signal(SIGUSR1, SIG_IGN);
    printf("%d\tBlocked now.\n", my_pid);
    printf("%d\tChild no %d is reading now.\n",my_pid, getpid());
    fd = open(filename, O_RDONLY | O_CREAT);

    char buf = 'a';
    int k=0;
    char* op = (char*) malloc (255*sizeof(char));

    while(read (fd, &buf, 1))
    {
        if (buf == '\n')
        {
            op[k] = '\0';
            break;
        }

        else
        {
            op[k++] = buf;
        }
    }

    //Now wait for a second and then send a signal
    sleep(1);
    //Print the contents of the buffer via op
    printf("%d\tOutput: %s\n", my_pid, op);


    //Now unblock the signal
    kill(getppid(), SIGUSR2);
    signal(SIGUSR1, sig_usr1);
    printf("%d\tUnblocked now\n", my_pid);
}

static void sig_usr2(int signo)
{
    if (signo == SIGUSR2)
    {
        printf("%d\tParent Received SIGUSR2. Child Process with PID %d is now free\n", my_pid, cpid[j]);
        kill (cpid[j++], SIGUSR1);
        if (j == no_of_children)
        {
            j = 0;
        }

    }
}

int main(int argc, char* argv[])
{
    my_pid = getpid();
    //Filename is the first argument
    filename = argv[1];

    //Number of Child Processes to be spawned
    no_of_children = atoi(argv[2]);

    cpid = (int*) malloc (no_of_children*sizeof(int));

    signal(SIGUSR2, sig_usr2);
    //Create no_of_children children
    for(int i=0; i<no_of_children; i++)
    {
        cpid[i] = fork();
        if (cpid[i] == 0)
        {
            //Inside a child
            my_pid = getpid();
            printf("%d\tCreated %dth child process", my_pid, i); 
            printf(" with Process ID = %d\n", getpid());            

            signal(SIGUSR1, sig_usr1);

            while(1)
            {
                pause();
            }

            //Every child process must exit so control goes back to the parent
            exit(0);
        }
        printf("%d\tforked %dth child -> %d\n", my_pid, i, cpid[i]);
    }

    //Returns to the parent process
    while(1)
    {
        int fpid = cpid[j];
        //Send the signal to the free child process
        printf("%d\tSending to PID %d\n", my_pid, fpid);
        kill(fpid, SIGUSR1);
        //j = (j < no_of_children - 1) ? j + 1 : 0;
        pause();
    }

    return 0;
}
您可以在每个进程自己的日志文件中为其创建日志。添加分辨率至少为毫秒的时间戳,以便稍后同步所有日志。这样可以避免在标准输出上出现输出混淆的问题。
还有很多事情需要解决。祝你玩得开心!祝你好运

请提供一个示例,并将编译器的警告级别提高到最大。尝试编译示例会产生太多错误。我编辑了我的文章以生成一个工作示例。你现在能查一下吗?谢谢,不是现在,因为我在工作,在那里我必须使用Windows。为了增加别人加入的机会,你还可以展示你期望的产出和你得到的。是的,当然。我还添加了输出。我所期望的是输出行一次显示4次,每1秒显示一次,因为在这一点上,所有4个进程读取文件pintf是信号不安全的。千万不要在信号处理器里做。谢谢你的回答。你的一些观点确实有帮助。我同意你的看法;父母向孩子们发送太多信号很可能是这里的错误。我确实想过在父对象的while循环中加入pause,但没有,因为这不是我所期望的输出。但我同意你的观点,你的改变包含了更好的编程实践,我可以遵循。通过这个问题,我学到了一些教训。再次感谢您的投入!我将此标记为答案,因为这为我完成任务指出了足够的见解
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<signal.h>
#include<fcntl.h>
#include<sys/wait.h>

int counter = 0;
int fd;
const char* filename;
int j = 0;
int no_of_children;
int* cpid;
int my_pid;

//User define signal handler
static void sig_usr1(int);
static void sig_usr2(int);

static void sig_usr1(int signo)
{
    //Now the child process waits for reading the Filename

    //Block SIGUSR1 until it's complete
    signal(SIGUSR1, SIG_IGN);
    printf("%d\tBlocked now.\n", my_pid);
    printf("%d\tChild no %d is reading now.\n",my_pid, getpid());
    fd = open(filename, O_RDONLY | O_CREAT);

    char buf = 'a';
    int k=0;
    char* op = (char*) malloc (255*sizeof(char));

    while(read (fd, &buf, 1))
    {
        if (buf == '\n')
        {
            op[k] = '\0';
            break;
        }

        else
        {
            op[k++] = buf;
        }
    }

    //Now wait for a second and then send a signal
    sleep(1);
    //Print the contents of the buffer via op
    printf("%d\tOutput: %s\n", my_pid, op);


    //Now unblock the signal
    kill(getppid(), SIGUSR2);
    signal(SIGUSR1, sig_usr1);
    printf("%d\tUnblocked now\n", my_pid);
}

static void sig_usr2(int signo)
{
    if (signo == SIGUSR2)
    {
        printf("%d\tParent Received SIGUSR2. Child Process with PID %d is now free\n", my_pid, cpid[j]);
        kill (cpid[j++], SIGUSR1);
        if (j == no_of_children)
        {
            j = 0;
        }

    }
}

int main(int argc, char* argv[])
{
    my_pid = getpid();
    //Filename is the first argument
    filename = argv[1];

    //Number of Child Processes to be spawned
    no_of_children = atoi(argv[2]);

    cpid = (int*) malloc (no_of_children*sizeof(int));

    signal(SIGUSR2, sig_usr2);
    //Create no_of_children children
    for(int i=0; i<no_of_children; i++)
    {
        cpid[i] = fork();
        if (cpid[i] == 0)
        {
            //Inside a child
            my_pid = getpid();
            printf("%d\tCreated %dth child process", my_pid, i); 
            printf(" with Process ID = %d\n", getpid());            

            signal(SIGUSR1, sig_usr1);

            while(1)
            {
                pause();
            }

            //Every child process must exit so control goes back to the parent
            exit(0);
        }
        printf("%d\tforked %dth child -> %d\n", my_pid, i, cpid[i]);
    }

    //Returns to the parent process
    while(1)
    {
        int fpid = cpid[j];
        //Send the signal to the free child process
        printf("%d\tSending to PID %d\n", my_pid, fpid);
        kill(fpid, SIGUSR1);
        //j = (j < no_of_children - 1) ? j + 1 : 0;
        pause();
    }

    return 0;
}
$ ./signal_repetition signal_repetition.c 4
1901                    forked 0th child -> 1902
    1902                Created 0th child process with Process ID = 1902
1901                    forked 1th child -> 1903
        1903            Created 1th child process with Process ID = 1903
1901                    forked 2th child -> 1904
            1904        Created 2th child process with Process ID = 1904
1901                    forked 3th child -> 1905
1901                    Sending to PID 1902
    1902                Blocked now.
    1902                Child no 1902 is reading now.
                1905    Created 3th child process with Process ID = 1905
    1902                Output: #include<stdio.h>
    1902                Unblocked now
1901                    Parent Received SIGUSR2. Child Process with PID 1902 is now free
1901                    Sending to PID 1903
    1902                Blocked now.
    1902                Child no 1902 is reading now.
1903                    Blocked now.
1903                    Child no 1903 is reading now.
    1902                Output: #include<stdio.h>
    1902                Unblocked now
1901                    Parent Received SIGUSR2. Child Process with PID 1903 is now free
1901                    Sending to PID 1904
            1904        Blocked now.
        1903            Output: #include<stdio.h>
            1904        Child no 1904 is reading now.
        1903            Unblocked now
        1903            Blocked now.
        1903            Child no 1903 is reading now.
1901                    Parent Received SIGUSR2. Child Process with PID 1904 is now free
1901                    Sending to PID 1905
                1905    Blocked now.
                1905    Child no 1905 is reading now.
        1903            Output: #include<stdio.h>
            1904        Output: #include<stdio.h>
        1903            Unblocked now
            1904        Unblocked now
            1904        Blocked now.
            1904        Child no 1904 is reading now.
1901                    Parent Received SIGUSR2. Child Process with PID 1905 is now free