进程的创建
fork函数: 它从已存在的进程中创建一个新进程. 新进程为子进程, 而原进程为父进程.
#include <unistd.h>
pid_t fork(void);
返回值: 子进程中返回0, 父进程返回子进程id, 出错返回-1
代码:
运行结果:
看到了三行输出, 一行before, 两行after. 进程10152先打印before消息, 然后打印after. 另一个after消息由10153打印的. fork之前父进程独立执行, fork之后, 父子两个执行流分别执行. fork之后, 谁先执行完全由调度器决定.
进程等待:
子进程退出, 父进程如果不管不顾, 就会造成僵尸进程的问题, 进而造成内存泄漏. 父进程需要通过进程等待的方式, 回收子进程资源, 获取子进程退出信息.
进程等待的方法:
wait
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
返回值:
成功返回被等待进程pid, 失败返回-1
参数:
输出型参数, 获取子进程退出状态, 不关心则可以设置成为null
waitpid
pid_t waitpid(pid_t pid, int *status, int options);
返回值:
当正常返回的时候waitpid返回收集到的子进程的进程id
如果设置了选项WNOHANG, 而调用中waitpid发现没有已退出的子进程可收集, 则返回0
如果调用中出错, 则返回-1, 这时errno会被设置成相应的值以指示错误所在
参数:
pid:
pid=-1, 等待任一个子进程. 与wait等效
pid>0. 等待其进程id与pid相等的子进程
status:
WIFEXITED(status): 若为正常终止子进程返回的状态, 则为真. (查看进程是否正常退出)
WEXITSTATUS(status): 若WIFEXITED非零, 提取子进程退出码. (查看进程的退出码)
options:
WNOHANG: 若pid指定的子进程没有结束, 则waitpid()函数返回0, 不予以等待. 若正常结束, 则返回该子进程的id
代码
运行结果:
进程终止:
常见退出方法:
正常终止:
1. 从main返回
2. 调用exit
3. _exit
异常退出:
Ctrl+c, 信号终止
_exit函数:
#include <unistd.h>
void _exit(int status);
参数: status定义了进程的终止状态, 父进程通过wait来获取该值
exit函数:
#include <unistd.h>
void exit(int status);
exit最后也会调用_exit, 但在调用_exit之前, 还做了其他工作
1. 执行用户通过atexit或on_exit定义的清理函数
2. 关闭所有打开的流, 所有的缓存数据均被写入
return退出:
return退出是一种常见的退出进程的方法, 执行return n等同于执行exit(0), 因为调用main的运行函数会将main的返回值当做exit的函数
实现一个简易的shell