UNIX环境高级编程-进程操作

1. 进程环境 #include <stdlib.h> void exit(int status); exit(0) 与 return 0 是等价的。 2. 进程标识和创建子进程 每个进程都有一个非负整型表示的唯一进程ID,但进程ID是可以被复用的。当一个进程终止后进程ID会进入候选池,并且一般新的进程不会使用最近终止进程的进程ID。 #include <unistd.h> pid_t getpid(void); // 返回值: 调用进程的进程ID pid_t getppid(void); // 返回值: 调用进程的父进程ID fork() 函数可以创建一个新进程,子进程和父进程继续执行fork调用之后的指令。子进程是父进程的副本。例如,子进程获得父进程数据空间、堆和栈的副本。并且在修改时使用了写时复制(Copy-On-Write,COW)技术。 #include <unistd.h> pid_t fork(void); // 返回值: 子进程返回0, 父进程返回子进程ID,若出错返回-1 以下是一个示例代码,用于创建一个子进程并展示父进程和子进程的ID与父进程ID,以及如何通过信号避免僵尸进程。 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> #include <sys/types.h> void sigchld_handler(int sig) { int status; pid_t id = waitpid(-1, NULL, WNOHANG); if (WIFEXITED(status)) { printf("remove proc id: %d \n", id); printf("Child send: %d \n", WEXITSTATUS(status)); } } int main(int argc, char *argv[]) { struct sigaction sa; sa.sa_handler = sigchld_handler; sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; // 初始化信号屏蔽集,确保不阻塞任何额外信号 sigemptyset(&sa.sa_mask); // 注册 SIGCHLD 信号处理 sigaction(SIGCHLD, &sa, NULL); pid_t pid; int val = 24; if ((pid = fork()) < 0) { fprintf(stderr, "fork err: %d\n", pid); exit(1); } else if (pid == 0) { val++; printf("child: pid = %d, ppid = %d\n", getpid(), getppid()); printf("child: val = %d\n", val); _exit(0); } else { sleep(5); printf("root: pid = %d, ppid = %d, child_pid = %d\n", getpid(), getppid(), pid); printf("root: val = %d\n", val); sleep(5); } exit(0); } 以下是执行程序后的结果,一个有意思点是程序的父进程ID是bash,子进程修改的数据并不会影响到父进程的数据。 ...

November 27, 2024 · 3 min · zhumouren