查询进程相关命令
ps aux
查看进程相关信息
1.就绪态、运行态 R
2.睡眠态、等待态
可唤醒等待态 S
不可唤醒等待态 D
3.停止态 T
4.僵尸态 Z
5.结束态
top
根据CPU占用率查看进程相关信息
kill 和killall
kill和killall发送一个信号
kill -2 PID 15
发送信号+PID对应的进程,默认接收者关闭
killall -9 进程名
发送信号 进程名对应的所有进程
killall a.out
进程相关函数
fork
pid_t fork(); //叉子
一次调用,会返回两次。
子进程先运行和是父进程先进程,顺序不确定。
变量不共享。
子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同。
- 功能
通过该函数可以从当前进程中克隆一个同名新进程。
克隆的进程称为子进程,原有的进程称为 父进程。
子进程是父进程的完全拷贝。
子进程的执行过程是从fork函数之后执行。
子进程与父进程具有相同的代码逻辑。
- 返回值
int 类型的数字。
在父进程中:成功 返回值是子进程的pid号 >0 失败 返回-1;
在子进程中:成功 返回值 0 失败 无
父子进程的关系:
子进程是父进程的副本。子进程获得父进程数据段,堆,栈,正文段共享。
在fork之后,一般情况那个会先运行,是不确定的。如果非要确定那个要先运行,需要IPC机制。
区别:
1)fork的返回值
2)pid不同
getpid
pid_t getpid(void);
- 功能
获得调用该函数进程的pid
- 参数
缺省
- 返回值
进程的pid
getppid
pid_t getppid(void);
- 功能
获得调用该函数进程的父进程pid号
- 参数
缺省
- 返回值
返回父进程id号
进程的终止
8种情况
1)main 中return
2)exit(), c库函数,会执行io库的清理工作,关闭所有的流,以及所有打开的文件。已经清理函数(atexit)。
3)_exit,_Exit 会关闭所有的已经打开的文件,不执行清理函数。
4) 主线程退出
5)主线程调用pthread_exit
异常终止
6)abort()
7)signal kill pid
8)最后一个线程被pthread_cancle
进程的退出
僵尸进程和孤儿进程
僵尸进程:进程执行结束但空间未被回收变成僵尸进程
- 僵尸进程 是已经结束但未被父进程回收的进程,虽然不占用大量系统资源,但占用进程表,需父进程及时处理。
- 孤儿进程 是父进程结束后仍在运行的子进程,会被
init
进程接管,正常运行,不会对系统造成危害。
exit
库函数
退出状态,终止的进程会通知父进程,自己使如何终止的。如果是正常结束(终止),则由exit传入的参数。如果是异常终止,则有内核通知异常终止原因的状态。任何情况下,负进程都能使用wait,waitpid获得这个状态,以及资源的回收。
void exit(int status);
exit(1);
- 功能
让进程退出,并刷新缓存区
- 参数
status:进程退出的状态
- 返回值
缺省
- 退出状态码
EXIT_SUCCESS 0表示成功。程序正常结束,操作系统认为该进程成功完成了所有任务
EXIT_FAILURE 1通常表示某种错误或异常。具体的含义取决于程序的设计和约定
exit -> 刷新缓存区 -> atexit注册的退出函数 -> _exit
return
return 当该关键字出现在main函数中时候可以结束进程
如果在其他函数中则表示结束该函数。
_exit
系统调用
void _exit(int status);
- 功能
让进程退出,不刷新缓存区
- 参数
status:进程退出状态
- 返回值
缺省
atexit
int atexit(void (*function)(void));
- 功能
注册进程退出前执行的函数
- 参数
function:函数指针
指向void返回值void参数的函数指针
- 返回值
成功返回0
失败返回非0
当程序调用exit或者由main函数执行return时,所有用atexit注册的退出函数,将会由注册时顺序倒序被调用
进程空间的回收
wait
wait/waitpid
进程退出
pid_t wait(int *status);
- 功能
该函数可以阻塞等待任意子进程退出并回收该进程的状态。
一般用于父进程回收子进程状态。(一次只回收一个)
- 参数
status 进程退出时候的状态
如果不关心其退出状态一般用NULL表示
如果要回收进程退出状态,则用WEXITSTATUS回收。
- 返回值
成功 回收的子进程pid
失败 -1;
int status;
pid_t pid = wait(&status);
- 宏函数
WIFEXITED(status) 是不是正常结束
检查子进程是否是通过调用 exit()
或者 return
正常退出的。如果是正常退出,返回非零值
WEXITSTATUS(status) 使用这个宏去拿返回值
当子进程正常结束时,可以用这个宏获取子进程的退出状态码(即子进程在 exit()
函数中传递的值8个bit位以内)。在 WIFEXITED(status)
为真时使用,用于获取子进程的退出码(exit()
或者 return
的值)。
在
wait()
函数中,status
是一个整型变量,用来保存子进程的终止状态。这个状态信息被编码在一个整数中,其中包括退出状态码、信号信息等。对于正常退出的子进程,
status
的高位存储的是子进程的退出码,而低位则用于标识子进程的其他状态信息。如果子进程正常退出,
status
的值可以用以下公式表示:status = exit_code << 8
WIFSIGNALED(status) 是不是收到了信号而终止的
如果返回非零值,表示子进程是因为接收到一个未捕获的信号而终止 。检查子进程是否是因为接收到一个未捕获的信号而终止。如果是信号终止,返回非零值
WTERMSIG(status)如果是信号终止的,那么是几号信号。
在 WIFSIGNALED(status)
为真时使用,用于获取导致子进程终止的信号编号
pid_t wait(int *status);
1)如果所有的子进程都在运行,在阻塞
2)如果一个子进程终止,正在等待的父进程则获得终止状态,获得子进程的状态后,立刻返回。
3)如果没有子进程,则立即出错退出。
waitpid
waitpid(-1,status,0)=wait(status);
pid_t waitpid(pid_t pid, int *status, int options);
< -1 回收指定进程组内的任意子进程
-1 回收任意子进程,组内外
0 回收和当前调用waitpid一个组的所有子进程,组内
> 0 回收指定ID的子进程
- 参数说明
pid
:
pid > 0
: 等待特定的子进程,其进程 ID 为 pid
。
pid == 0
: 等待任意子进程,其进程组 ID 与调用进程相同。
pid < -1
: 等待特定进程组的任意子进程,其进程组 ID 为 -pid
。
pid == -1
: 等待任意子进程(这与 wait
的行为相同)。
status
:
一个指向整数的指针,用于存储子进程的退出状态。如果你不关心子进程的退出状态,可以传递 NULL
。
options
:
0
: 默认行为,调用进程会阻塞,直到一个子进程结束。
WNOHANG
: 非阻塞模式。如果没有子进程结束,waitpid
会立即返回 0
,而不会阻塞。
-
返回值
成功: 返回被收集的子进程的 PID。
失败: 返回 -1
,并设置 errno
以指示错误。
waitpid
与wait
的关系
wait(a)
等价于waitpid(-1, a, 0)
,即等待任意子进程结束并阻塞,直到有子进程结束。waitpid(-1, a, 0)
会阻塞等待任意一个子进程结束,返回结束的子进程 PID,并将其退出状态存储在a
中。