SIGSTOP
和
SIGCONT
特别地。
这是我写的一个测试程序。这个想法是创建一个N+1的链
过程(包括主过程)。每个人都要等孩子停下来,然后停下来
停止。
f
函数递归地创建流程链。每个
进程在
SIGCHLD
与最后一个信号不同的信号
将收到
西格尔德
发出信号,然后它可以在转弯时停止。什么时候
主进程接收
西格尔德
进程处于停止状态,因此它发送
西格康特
向its发出信号
小孩每个进程发送
西格康特
给自己的孩子,然后离开,分开
从刚刚离开的最后一个孩子。
我试图澄清:删除了返回代码测试并编写了一些
评论。
执行程序时,一切似乎都正常,但
西格康特
链条一些进程被唤醒,但不是所有进程都被唤醒。查看
运行程序(例如使用ps)一切看起来都很好:否
阻塞进程。我真的不明白这有什么不对
这是一个示例跟踪。正如您所看到的,“分叉链”运行良好,进程挂起
西格尔德
西格尔德
因为每个进程都会停止自己。当主进程收到
西格尔德
它发送
西格康特
它的孩子被唤醒,然后
西格康特
$ ./bin/trycont
n pid log
0 6257 "suspending on SIGCHLD"
1 6258 "suspending on SIGCHLD"
2 6259 "suspending on SIGCHLD"
3 6260 "suspending on SIGCHLD"
4 6261 "suspending on SIGCHLD"
5 6262 "last child - stopping"
4 6261 "got SIGCHLD"
4 6261 "stopping"
3 6260 "got SIGCHLD"
3 6260 "stopping"
2 6259 "got SIGCHLD"
2 6259 "stopping"
1 6258 "got SIGCHLD"
1 6258 "stopping"
0 6257 "got SIGCHLD"
0 6257 "sending SIGCONT to 6258"
1 6258 "awakened - sending SIGCONT to 6259"
2 6259 "awakened - sending SIGCONT to 6260"
以下是程序:
src/trycont.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#define N 5
#define printHeader() printf("n\tpid\tlog\n");
#define printMsg(i, p, str, ...) printf("%d\t%d\t" #str "\n", i, p, ##__VA_ARGS__)
void f(int n);
void handler(int sig);
sigset_t set;
struct sigaction action;
int main(int argc, char *argv[])
{
sigemptyset(&set);
sigaddset(&set, SIGCHLD);
sigprocmask(SIG_SETMASK, &set, NULL);
action.sa_mask = set;
action.sa_handler = handler;
action.sa_flags = 0;
sigaction(SIGCHLD, &action, NULL);
printHeader();
f(N);
exit(EXIT_SUCCESS);
}
void f(int n)
{
pid_t p, pc;
int myIndex;
myIndex = N - n;
p = getpid();
if (n == 0)
{
printMsg(myIndex, p, "last child - stopping");
kill(p, SIGSTOP);
printMsg(myIndex, p, "END REACHED");
exit(EXIT_SUCCESS);
}
pc = fork();
if (pc == 0)
{
f(n - 1);
}
printMsg(myIndex, p, "suspending on SIGCHLD");
sigfillset(&set);
sigdelset(&set, SIGCHLD);
sigsuspend(&set);
printMsg(myIndex, p, "got SIGCHLD");
if (n < N)
{
printMsg(myIndex, p, "stopping");
kill(p, SIGSTOP);
printMsg(myIndex, p, "awakened - sending SIGCONT to %d", pc);
kill(pc, SIGCONT);
}
else
{
printMsg(myIndex, p, "sending SIGCONT to %d", pc);
kill(pc, SIGCONT);
}
exit(EXIT_SUCCESS);
}
void handler(int sig)
{
switch (sig)
{
case SIGCHLD:
action.sa_handler = SIG_IGN;
sigaction(SIGCHLD, &action, NULL);
break;
default:
break;
}
}
如果您需要,这里有一个Makefile:
CC=gcc
DEFINES=-D_POSIX_C_SOURCE
STD=-std=c11 -Wall -Werror
OPTS=-O2
CFLAGS=$(STD) $(DEFINES) $(OPTS) -g
LDFLAGS=
SRC=src
OBJ=obj
BIN=bin
DIRS=$(BIN) $(OBJ)
.PHONY: mkdirs clean distclean
all: mkdirs $(BIN)/trycont
$(BIN)/%: $(OBJ)/%.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
$(OBJ)/%.o: $(SRC)/%.c
$(CC) $(CFLAGS) -c -o $@ $<
mkdirs:
- mkdir $(DIRS)
clean:
rm -vf -- $(OBJ)/*.o
distclean: clean
rm -vfr -- $(DIRS)