gpt4 book ai didi

c - SIGSTOP/SIGCONT POSIX 行为

转载 作者:行者123 更新时间:2023-12-04 02:09:31 28 4
gpt4 key购买 nike

我正在研究信号:特别是 SIGSTOPSIGCONT。这是我写的一个测试程序。这个想法是创建一个 N + 1 的链进程(包括主进程)。每个人都必须等待它的 child 停止,然后停止本身。当后者有停止了。

为此,f 函数递归地创建流程链。每一个该进程在 SIGCHLD 信号上使用 sigsuspend,除了最后一个直接停下自己的 child 。当它的 child 停止时,一个进程将接收到 SIGCHLD 信号,然后它可以在轮到它时停止。什么时候主进程收到 SIGCHLD 信号,这意味着所有的进程处于停止状态,因此它向其发送 SIGCONT 信号 child 。每个进程发送 SIGCONT 给自己的子进程然后退出,分开来自刚刚退出的最后一个 child 。

我试图说清楚:删除了返回码测试并写了一些评论。

当执行程序时,一切似乎都很好,但 SIGCONT链。一些进程被唤醒,但不是全部。看着运行程序(例如使用 ps)一切似乎都很好:否阻塞的进程。我真的不明白这有什么问题程序。欢迎任何帮助或提示。

这是一个示例跟踪。如您所见,“ fork 链”运行良好,进程因 SIGCHLD 而暂停。然后最后一个 child 产卵并停止。这会在父级上创建一个“SIGCHLD 链”,因为每个进程都会自行停止。当主进程收到 SIGCHLD 的通知时,它会向其子进程发送 SIGCONT,该子进程被唤醒并依次向其自己的子进程发送 SIGCONT等等。你会注意到这条链是不完整的:

$ ./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"
# <- not the expected trace

这是程序:src/trycont.c

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

/* number of created processes with fork
*/
#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[])
{
/* mask SIGCHLD
*/
sigemptyset(&set);
sigaddset(&set, SIGCHLD);
sigprocmask(SIG_SETMASK, &set, NULL);

/* handler will be called when SIGCHLD is sent to the process
* during the handler, SIGCHLD will be masked (sa_mask)
*/
action.sa_mask = set;
action.sa_handler = handler;
action.sa_flags = 0;

/* SIGCHLD will trigger action
*/
sigaction(SIGCHLD, &action, NULL);

/* start
*/
printHeader();
f(N);

exit(EXIT_SUCCESS);
}

void f(int n)
{
pid_t p, pc;
int myIndex;

myIndex = N - n;
p = getpid();

if (n == 0)
{
/* last child
*/
printMsg(myIndex, p, "last child - stopping");
kill(p, SIGSTOP);
printMsg(myIndex, p, "END REACHED");
exit(EXIT_SUCCESS);
}

pc = fork();

if (pc == 0)
{
/* recursion
*/
f(n - 1);

/* never reached
* because of exit
*/
}

/* father
*/

/* suspending on SIGCHLD
* need to unmask the signal
* and suspend
*/
printMsg(myIndex, p, "suspending on SIGCHLD");

sigfillset(&set);
sigdelset(&set, SIGCHLD);
sigsuspend(&set);

printMsg(myIndex, p, "got SIGCHLD");

if (n < N)
{
/* child process
* but not last
*/
printMsg(myIndex, p, "stopping");
kill(p, SIGSTOP);

printMsg(myIndex, p, "awakened - sending SIGCONT to %d", pc);
kill(pc, SIGCONT);
}
else
{
/* root process
*/
printMsg(myIndex, p, "sending SIGCONT to %d", pc);
kill(pc, SIGCONT);
}

exit(EXIT_SUCCESS);
}

void handler(int sig)
{
switch (sig)
{
case SIGCHLD:
/* when the process received SIGCHLD
* we can ignore upcoming 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)

最佳答案

当第一个进程终止时,您的某些(全部?)后代进程正在死于系统生成的 SIGHUP。

这是 expected POSIX behavior在某些情况下。

当您从 shell 启动根进程时,它是一个进程组组长,它的后代是该组的成员。当该领导者终止时,进程组将孤立。当系统检测到任何成员停止的新孤立进程组时,进程组的每个成员都会收到一个 SIGHUP,然后是一个 SIGCONT。

因此,当领导者终止时,您的一些后代进程仍会停止,因此每个人都会收到一个 SIGHUP,然后是一个 SIGCONT,这实际上意味着他们死于 SIGHUP。

究竟哪些后代仍然停止(或者甚至只是愉快地向 exit() 前进)是一场计时赛跑。在我的系统上,领导者很快终止,以至于没有一个后代能够打印任何东西。

关于c - SIGSTOP/SIGCONT POSIX 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40029116/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com