目录
- 基础API
- fork
- wait与waitpid
- getpid与getppid
- getuid与geteuid
- getgid与getegid
- 实例程序
- 全局变量的共享问题
- 孤儿进程
- 僵尸进程
基础API
fork
头文件: #include <unistd.h>
pid_t fork(void);
创建一个子进程
pid_t类型表示进程ID, 但为了表示-1, 它是有符号整型. 0不是有效进程ID, init最小为1
返回值:
失败: -1
成功: 通过返回值判断父子进程. (1) 父进程返回子进程的ID(非负值); (2) 子进程返回 0
**注意: 不是fork函数能返回两个值, 而是fork后, fork函数变为两个, 父子需各自返回一个 **
wait与waitpid
头文件:
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
阻塞函数调用一次回收一个子进程资源
返回值:
-1: 回收失败, 已经没有子进程了
>0: 回收是子进程对应的pid
参数:
status: 传出参数, 用于判断子进程终止原因. 可使用下面三组宏函数判断终止原因
WIFEXITED(status)
非0 --> 进程正常退出: return; exit;
WEXITSTATUS(status)
进一步获取进程退出状态
WIFSIGNALED(status)
非0 --> 进程异常终止
WTERMSIG(status)
取得使进程终止的那个信号的编号
WIFSTOPPED(status)
非0 --> 进程处于暂停状态
WSTOPSIG(status)
取得使进程暂停的那个信号的编号
WIFCONTINUED(status)
为真, 进程暂停后已经继续运行
pid_t waitpid(pid_t pid, int *status, int options);
一次只回收一个进程
参数:
pid > 0: 某个子进程的pid
pid == -1: 回收所有的子进程, 循环回收
pid == 0: 回收当前进程组的所有子进程
pid < -1: 回收当前进程组内的任意子进程, 取翻(加减号)
status: 子进程的退出状态, 用法同wait函数
opttions: 0, 阻塞; WNOHANG, 非阻塞
返回值:
-1: 回收失败, 没有子进程
>0: 被回收的子进程
=0: 参3为WNOHANG, 且子进程正在运行
getpid与getppid
头文件:
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
获取当前进程的ID
pid_t getppid(void);
获取当前进程的父ID
getuid与geteuid
头文件:
#include <unistd.h>
#include <sys/types.h>
uid_t getuid(void);
获取当前进程实际用户ID
uid_t geteuid(void);
获取当前用户有效用户ID
getgid与getegid
头文件
#include <unistd.h>
#include <sys/types.h>
gid_t getgid(void);
获取当前进程使用用户组ID
gid_t getegid(void);
获取当前进程有效用户组ID
实例程序
全局变量的共享问题
普通全局变量没有共享, 但是地址空间相同
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
int counter = 200;
int main(int argc, const char* argv[])
{
int i;
pid_t pid;
for(i=0; i<5; ++i) { // 通过i可区分进程
pid = fork();
if(pid == 0) // 子进程跳出for循环
break;
}
if(i<5) {
counter += 300;
printf(" child process , pid = %d, ppid = %d\n", getpid(), getppid());
printf("counter = %d, &counter = %p\n\n", counter, &counter);
}
else if(i == 5) {
counter += 100;
printf(" parent process, pid = %d, ppid = %d, &counter = %p\n", getpid(), getppid(), &counter);
printf("counter = %d, &counter = %p\n\n", counter, &counter);
sleep(1);
}
return 0;
}
/*
child process , pid = 25474, ppid = 25473
counter = 500, &counter = 0x60104c
parent process, pid = 25473, ppid = 22642, &counter = 0x60104c
counter = 300, &counter = 0x60104c
child process , pid = 25475, ppid = 25473
counter = 500, &counter = 0x60104c
child process , pid = 25476, ppid = 25473
counter = 500, &counter = 0x60104c
child process , pid = 25477, ppid = 25473
counter = 500, &counter = 0x60104c
child process , pid = 25478, ppid = 25473
counter = 500, &counter = 0x60104c
*/
孤儿进程
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
int main(void) {
pid_t pid;
printf("haha\n");
pid = fork();
if (pid < 0) {
perror("fork error");
exit(1);
}
else if (pid == 0) {
printf("child, pid: %d, ppid: %d\n", getpid(), getppid());
sleep(1);
}
else {
printf("parent, pid: %d\n, ppid: %d\n", getpid(), getppid());
}
printf("haha\n");
return 0;
}
/*
[zyb@server fork]$ ./a.out
haha
parent, pid: 25654
, ppid: 22642
haha
[zyb@server fork]$ child, pid: 25655, ppid: 1
haha
[zyb@server fork]$
*/
僵尸进程
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
int main(void) {
pid_t pid;
printf("haha\n");
pid = fork();
if (pid < 0) {
perror("fork error");
exit(1);
}
else if (pid == 0) {
printf("child, pid: %d, ppid: %d\n", getpid(), getppid());
sleep(1);
}
else {
while (1) {
printf("parent, pid: %d\n, ppid: %d\n", getpid(), getppid());
sleep(5);
}
}
printf("haha");
return 0;
}
/*
[zyb@server ~]$ ps aux | grep "a.out"
zyb 27627 0.0 0.0 4212 344 pts/0 S+ 22:50 0:00 ./a.out
zyb 27628 0.0 0.0 0 0 pts/0 Z+ 22:50 0:00 [a.out] <defunct>
zyb 27630 0.0 0.0 112704 968 pts/1 S+ 22:50 0:00 grep --color=auto a.out
*/