gpt4 book ai didi

shell - ExitCodes 大于 255,可能吗?

转载 作者:行者123 更新时间:2023-12-03 08:48:13 28 4
gpt4 key购买 nike

如果是,在哪个操作系统、shell 或其他什么操作系统上?

考虑下面的java程序(我使用java只是作为例子,任何语言都适合这个问题,更多的是关于操作系统):

public class ExitCode {
public static void main(String args[]) {
System.exit(Integer.parseInt(args[0]));
}
}

在 Linux 和 bash 上运行它,它返回的值总是小于等于 255,例如( echo $? 打印上一条执行命令的退出码)
> java ExitCode 2; echo $?
2

> java ExitCode 128; echo $?
128

> java ExitCode 255; echo $?
255

> java ExitCode 256; echo $?
0

> java ExitCode 65536; echo $?
0

已编辑:下面的(迄今为止唯一的)答案充分解释了 UNIX 上发生的情况。我仍然想知道其他操作系统。

最佳答案

使用 wait()waitpid()
在使用 POSIX 函数(如 wait() )的 Unix 和衍生产品上是不可能的和 waitpid() .返回的退出状态信息由两个 8 位字段组成,一个包含退出状态,另一个包含有关死因的信息(0 表示在程序控制下有序退出,其他值表示信号杀死它,并表示是否一个核心被倾倒了)。

使用 sigaction()SA_SIGINFO
如果你努力工作,并阅读 sigaction() 的 POSIX 规范和 <signal.h> Signal Actions ,你会发现可以拿到传递给exit()的32位值通过子进程。然而,这并不完全是直截了当的。

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

static siginfo_t sig_info = { 0 };
static volatile sig_atomic_t sig_num = 0;
static void *sig_ctxt = 0;

static void catcher(int signum, siginfo_t *info, void *vp)
{
sig_num = signum;
sig_info = *info;
sig_ctxt = vp;
}

static void set_handler(int signum)
{
struct sigaction sa;
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = catcher;
sigemptyset(&sa.sa_mask);

if (sigaction(signum, &sa, 0) != 0)
{
int errnum = errno;
fprintf(stderr, "Failed to set signal handler (%d: %s)\n", errnum, strerror(errnum));
exit(1);
}
}

static void prt_interrupt(FILE *fp)
{
if (sig_num != 0)
{
fprintf(fp, "Signal %d from PID %d (status 0x%.8X; UID %d)\n",
sig_info.si_signo, (int)sig_info.si_pid, sig_info.si_status,
(int)sig_info.si_uid);
sig_num = 0;
}
}

static void five_kids(void)
{
const int base = 0xCC00FF40;
for (int i = 0; i < 5; i++)
{
pid_t pid = fork();
if (pid < 0)
break;
else if (pid == 0)
{
printf("PID %d - exiting with status %d (0x%.8X)\n",
(int)getpid(), base + i, base + i);
exit(base + i);
}
else
{
int status = 0;
pid_t corpse = wait(&status);
if (corpse != -1)
printf("Child: %d; Corpse: %d; Status = 0x%.4X - waited\n", pid, corpse, (status & 0xFFFF));
struct timespec nap = { .tv_sec = 0, .tv_nsec = 1000000 }; // 1 millisecond
nanosleep(&nap, 0);
prt_interrupt(stdout);
fflush(0);
}
}
}

int main(void)
{
set_handler(SIGCHLD);
five_kids();
}

运行时(程序 sigexit73sigexit73.c 编译),会产生如下输出:
$ sigexit73
PID 26599 - exiting with status -872349888 (0xCC00FF40)
Signal 20 from PID 26599 (status 0xCC00FF40; UID 501)
Child: 26600; Corpse: 26599; Status = 0x4000 - waited
PID 26600 - exiting with status -872349887 (0xCC00FF41)
Signal 20 from PID 26600 (status 0xCC00FF41; UID 501)
Child: 26601; Corpse: 26600; Status = 0x4100 - waited
PID 26601 - exiting with status -872349886 (0xCC00FF42)
Signal 20 from PID 26601 (status 0xCC00FF42; UID 501)
Child: 26602; Corpse: 26601; Status = 0x4200 - waited
PID 26602 - exiting with status -872349885 (0xCC00FF43)
Signal 20 from PID 26602 (status 0xCC00FF43; UID 501)
Child: 26603; Corpse: 26602; Status = 0x4300 - waited
PID 26603 - exiting with status -872349884 (0xCC00FF44)
Signal 20 from PID 26603 (status 0xCC00FF44; UID 501)
$

一毫秒调用 nanosleep()删除,输出很容易看起来像:
$ sigexit73
sigexit23
PID 26621 - exiting with status -872349888 (0xCC00FF40)
Signal 20 from PID 26621 (status 0xCC00FF40; UID 501)
Child: 26622; Corpse: 26621; Status = 0x4000 - waited
PID 26622 - exiting with status -872349887 (0xCC00FF41)
PID 26623 - exiting with status -872349886 (0xCC00FF42)
Signal 20 from PID 26622 (status 0xCC00FF41; UID 501)
Child: 26624; Corpse: 26623; Status = 0x4200 - waited
Signal 20 from PID 26623 (status 0xCC00FF42; UID 501)
Child: 26625; Corpse: 26622; Status = 0x4100 - waited
PID 26624 - exiting with status -872349885 (0xCC00FF43)
PID 26625 - exiting with status -872349884 (0xCC00FF44)
$

请注意,只有三行以 Signal 开头在这里,也只有三行结尾 waited ;一些信号和退出状态丢失。这很可能是因为 SIGCHLD 之间的时间问题。信号被设置到父进程。

但是,关键是在 exit()中可以传输4个字节的数据。代码使用时的状态 sigaction() , SIGCHLD , SA_SIGINFO跟踪状态。

只是为了记录,测试是在运行 macOS Mojave 10.14.6 的 MacBook Pro 上执行的,使用 GCC 9.2.0 和 XCode 11.3.1。代码也可以在我的 SOQ 中找到(堆栈溢出问题)GitHub 上的存储库作为文件 sigexit73.csrc/so-1843-7779子目录。

关于shell - ExitCodes 大于 255,可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/179565/

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