进程标识符
#include <unistd.h>
pid_t getpid(void); //获得调用进程的PID
pid_t getppid(void); //获得调用进程的父进程的PID
uid_t getuid(void); //返回调用进程的实际用户ID
uid_t geteuid(void); //返回调用进程的有效用户ID
gid_t getgid(void0; //返回调用进程的实际组ID
gid_t getegid(void); //返回调用进程的有效组ID
fork函数
#include <unistd.h>
pid_t fork(void); //返回值,子进程中返回0,父进程中返回子进程ID,出错返回-1
e8-1演示了fork函数,从中可以看出,子进程对变量所做的修改并不影响父进程中该变量。
#include "apue.h"
int glob = 6;
char buf[] = "a write to stdout\n";
int main(void) {
int var;
pid_t pid;
var = 88;
if (write(STDOUT_FILENO, buf, sizeof(buf) - 1) != sizeof(buf) - 1)
err_sys("write error");
if ((pid = fork()) < 0) {
err_sys("fork error");
} else if (pid == 0) {
glob ++;
++ var;
} else {
sleep(2);
}
printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
exit(0);
}
C标准IO库是有缓冲区的。如果标准输出连接的是终端设备,则它是行缓冲的。否则它是全缓冲的。所以在终端中运行该程序,在fork时,缓冲区已经被刷新了,因为上面的printf输出的刚好是一行。子进程的缓冲区和父进程完全一致,所以它的缓冲区也是已经被刷新了。所以printf只输出一次。 如果将其标准输出重定向到一个文件,则会输出2次。
wait和waitpid函数
当一个进程终止时,内核向其父进程发送SIGCHLD信号。如果进程在收到SIGCHLD信号时调用wait,则可期望wait会立刻返回。如果在任意时刻调用,则进程可能会阻塞。
#include <sys/wait.h>
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);
wait和waitpid的区别如下:
- 在一个进程终止前,wait使其调用者阻塞,而waitpid有一个选项,可使调用者不阻塞。
- waitpid并不等待在其调用之后的第一个终止子进程,它有若干个选项,可以控制特定的子进程
如果一个进程终止了,并且是一个僵尸进程,则wait立刻返回,并取得该子进程的状态,否则wait使调用者一直阻塞到一个子进程终止。
这两个函数的参数statloc是一个整型指针。如果statloc不是空指针,则终止进程的终止状态就存放在它所指向的单元里。如果不关心终止状态,则可以置为空指针。
终止原因可以通过以下的宏来查询宏 说明 WIFEXITED(status) 若为正常终止子进程,返回真。对于这种情况可以通过WEXITSTATUS来取得返回值 WIFSIGNALED(status) 若为异常终止子进程返回,则为真。可通过WTERMSIG,来获得终止的信号。 WIFSTOPPED(status) 若为当前暂停子进程的返回状态,则为真。可通过WSTOPSIG,取得子进程暂停的信号 WIFCONTINUED(status) 若在作业控制暂停后,已经继续的子进程,则为真。