Skip to content

Instantly share code, notes, and snippets.

@SarKerson
Created December 20, 2018 02:20
Show Gist options
  • Save SarKerson/5a63e2d668c749153e237ed2d4acb352 to your computer and use it in GitHub Desktop.
Save SarKerson/5a63e2d668c749153e237ed2d4acb352 to your computer and use it in GitHub Desktop.

version3_利用sigprocmask同步父子进程

期望输出: done fork先于got signal,某一刻出现的done fork数量大于等于got signal

code:

#include <sys/wait.h>
#include <sys/signal.h>
#include <errno.h>
#include "apue.h"

volatile int counter = 0;

void handler(int sig)
{
    char msg[] = "# Got signal from child!\n";
    int olderrno = errno; // 保存错误
    sigset_t mask_all, mask_pre;
    sigfillset(&mask_all);
    while ((waitpid(-1, NULL, 0)) > 0) {
        sigprocmask(SIG_BLOCK, &mask_all, &mask_pre);
        write(STDOUT_FILENO, msg, strlen(msg));
        ++counter;
        sigprocmask(SIG_UNBLOCK, &mask_pre, NULL);
    }
    if (errno != ECHILD) // 因为跳出上面循环的条件中,预料之中的是找不到运行中的子进程
        printf("waitpid error\n");
    errno = olderrno;
}

int main()
{
    if (signal(SIGCHLD, handler) == SIG_ERR) {
        printf("signal error\n");
    }
    sigset_t mask_one, mask_pre;
    sigemptyset(&mask_one);
    sigaddset(&mask_one, SIGCHLD);
    signal(SIGCHLD, handler);
    for (int i = 0; i < 10; ++i) {
        sigprocmask(SIG_BLOCK, &mask_one, &mask_pre);
        if (fork() == 0) {
            // child
            char msg[] = "Hello from child\n";
            write(STDOUT_FILENO, msg, strlen(msg));
        //    sleep(1);
            exit(0);
        }
        char msg[] = "# Done fork()\n";
        write(STDOUT_FILENO, msg, strlen(msg));
        sigprocmask(SIG_SETMASK, &mask_pre, NULL);
        sleep(1);
    }
    printf("Process from parent\n");
    sleep(10);
    while (1) {
        pause();
        printf("count: %d\n", counter);
    }
    exit(0);
}

result:预料之中,先父再子

# Done fork()
Hello from child
# Got signal from child!
# Done fork()
Hello from child
# Got signal from child!
# Done fork()
Hello from child
# Got signal from child!
# Done fork()
Hello from child
# Got signal from child!
# Done fork()
Hello from child
# Got signal from child!
# Done fork()
Hello from child
# Got signal from child!
# Done fork()
Hello from child
# Got signal from child!
# Done fork()
Hello from child
# Got signal from child!
# Done fork()
Hello from child
# Got signal from child!
# Done fork()
Hello from child
# Got signal from child!
Process from parent

version1_父子进程乱序运行

code:

#include <sys/wait.h>
#include <sys/signal.h>
#include <errno.h>
#include "apue.h"

volatile int counter = 0;

void handler(int sig)
{
    char msg[] = "# Got signal from child!\n";
    int olderrno = errno; // 保存错误
    while ((waitpid(-1, NULL, 0)) > 0) {
        write(STDOUT_FILENO, msg, strlen(msg));
        ++counter;
    }
    if (errno != ECHILD) // 因为跳出上面循环的条件中,预料之中的是找不到运行中的子进程
        printf("waitpid error\n");
    errno = olderrno;
}

int main()
{
    if (signal(SIGCHLD, handler) == SIG_ERR) {
        printf("signal error\n");
    }

    for (int i = 0; i < 10; ++i) {

        if (fork() == 0) {
            // child
            char msg[] = "Hello from child\n";
            write(STDOUT_FILENO, msg, strlen(msg));
        //    sleep(1);
            exit(0);
        }
        char msg[] = "# Done fork()\n";
        write(STDOUT_FILENO, msg, strlen(msg));
    }
    printf("Process from parent\n");
    sleep(10);
    while (1) {
        pause();
        printf("count: %d\n", counter);
    }
    exit(0);
}

result:

# Done fork()
# Done fork()
Hello from child
Hello from child
# Done fork()
# Done fork()
Hello from child
Hello from child
# Got signal from child!
# Got signal from child!
# Got signal from child!
# Got signal from child!
# Done fork()
# Done fork()
Hello from child
Hello from child
# Done fork()
# Done fork()
Hello from child
# Got signal from child!
# Got signal from child!
Hello from child
# Got signal from child!
Hello from child
# Got signal from child!
# Got signal from child!
# Done fork()
# Done fork()
Hello from child
Process from parent
# Got signal from child!

version2_测试pause的效果

code:

#include <sys/wait.h>
#include <sys/signal.h>
#include <errno.h>
#include "apue.h"

volatile int counter = 0;

void handler(int sig)
{
    char msg[] = "# Got signal from child!\n";
    int olderrno = errno; // 保存错误
    while ((waitpid(-1, NULL, 0)) > 0) {
        write(STDOUT_FILENO, msg, strlen(msg));
        ++counter;
    }
    if (errno != ECHILD) // 因为跳出上面循环的条件中,预料之中的是找不到运行中的子进程
        printf("waitpid error\n");
    errno = olderrno;
}

int main()
{
    if (signal(SIGCHLD, handler) == SIG_ERR) {
        printf("signal error\n");
    }

    for (int i = 0; i < 10; ++i) {
        if (fork() == 0) {
            // child
            char msg[] = "Hello from child\n";
            write(STDOUT_FILENO, msg, strlen(msg));
            sleep(1);
            exit(0);
        }
        char msg[] = "# Done fork()\n";
        write(STDOUT_FILENO, msg, strlen(msg));
    }
    printf("Process from parent\n");
    while (1) {
        pause();
        printf("count: %d\n", counter);
    }
    exit(0);
}

result:

# Done fork()
# Done fork()
Hello from child
Hello from child
# Done fork()
Hello from child
# Done fork()
Hello from child
# Done fork()
Hello from child
# Done fork()
Hello from child
# Done fork()
Hello from child
# Done fork()
Hello from child
# Done fork()
Hello from child
# Done fork()
Hello from child
Process from parent
# Got signal from child!
# Got signal from child!
# Got signal from child!
# Got signal from child!
# Got signal from child!
# Got signal from child!
# Got signal from child!
# Got signal from child!
# Got signal from child!
# Got signal from child!
count: 10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment