gpt4 book ai didi

C 代码适用于 Mac (Darwin 13.4),但不适用于 Linux (2.6.32)

转载 作者:太空宇宙 更新时间:2023-11-04 13:01:00 24 4
gpt4 key购买 nike

我正在为一个类(class)编写一个玩具外壳程序,我在我的 mac (Darwin 13.4.0) 上完成了所有编码并使用 gcc <programname> -o <executablename> 进行了编译。 .一切似乎都运行完美。然后我将源代码通过 ftp 传输到学校的 Linux 服务器并再次编译,使用完全相同的编译指令,但在 Linux 机器上代码有错误。特别是,sigaction(信号处理程序)似乎并不总是正常工作。似乎它没有可靠地捕获 SIGCHLD 信号。 编辑——实际上,我存储状态的变量被破坏了,所以前台进程显示的状态不正确。

有人知道为什么操作系统的更改会导致此类问题吗?

这是我的信号处理程序代码:

void handleSignal(int signal){
int childid = 0;
int tempStatus = 0;

while ( (childid = waitpid(-1, &childStatus, WNOHANG)) > 0) {

/*Parse the exit status */
if(WIFEXITED(childStatus)){
childStatus = WEXITSTATUS(childStatus);
}
switch (signal) {

/*if the signal came from a child */
case SIGCHLD:

/*for background processes alert user */
if (childid != foregroundProcess){

printf("pid %i terminated:",childid);
showStatus(childStatus);
fflush(stdout);
}

/* for foreground children ending, just set the temp Status, in case*/
/* background children also need to be caught */
else {
tempStatus = childStatus;
}

break;

case SIGINT:

/*If there is a foreground child, send signal to it, else ignore. */
if (foregroundProcess){
kill(foregroundProcess, signal);
}
break;

default:
printf("Some other signal was received: code %i\n", signal);
fflush(stdout);
}
}
childStatus = tempStatus; /* reset child status to foreground status */
}

编辑:添加注册信号处理程序的代码:

struct sigaction sa;
sa.sa_handler = &handleSignal; /*passing function ref. to handler */
sa.sa_flags = SA_RESTART; /* restart the shell signal handler */
sigfillset(&sa.sa_mask); /*block all other signals while handling sigs */

sigaction(SIGINT, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);

最佳答案

无视。解决了。这就是问题所在:我在主程序循环中等待前台子进程,我也在信号处理程序中等待它。在主循环中,我使用了 waitoptions = 0,因此程序会等待,并且在处理程序 WNOHANG 中。

那么为什么它在 Linux 和 Darwin 中的表现不同呢?这是我的理论:在 Darwin 盒子上,当 child 死亡时,SIGCHLD 信号在父循环中的 waitpid 发现 child 已经死亡之前被传递和处理。所以信号处理程序处理了垂死的前景 child 。然后,当执行返回到主循环中的 waitpid 命令时,不存在具有该 pid 的子进程,waitpid 函数返回错误 -1。但是,我没有检查 waitpid 调用的返回值,这意味着错误对我来说是无声的,程序在 Darwin 机器上运行正常。

然而,在 Linux 机器中,主程序循环中的 waitpid 在信号处理程序之前先执行。因此 childstatus 将在主程序循环中设置(正确)。然后,当信号处理程序捕获 SIGCHLD 信号时,进程已经等待。所以 waitpid 返回错误 (-1, errno 10)。但是由于我在信号处理程序中处理子状态变量的方式(使用 childStatus 和 tempStatus),这种情况会破坏我的子状态,将其重置回 0。因此,在 Linux 上运行时,每个前景子状态都显示为 0 的退出状态机,但在 Mac 上有适当的退出状态。解决方案?将 tempStatus 声明更改为 int tempStatus = childStatus。这样,如果 childStatus 已被前台进程设置,则跳过整个循环并保持状态。但是,如果代表后台进程调用信号处理程序,则信号处理程序会保存前台状态(如果存在),并在处理后台时显示后台状态,然后重置前台状态。

丑陋...但它足以在几个小时内达到一个等级。

我不知道这是否会对其他人有所帮助,但是嘿,它可能会。谈论令人沮丧!

关于C 代码适用于 Mac (Darwin 13.4),但不适用于 Linux (2.6.32),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33879376/

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