一、exit(status)和_exit(status)
- exit(status) : 退出进程是会查看当前进程的IO缓冲区,把IO缓冲区的内容打印出到标椎输出(屏幕)
- _exit(status) : 直接退出进程,不会打印出IO缓冲区的内容
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
//exit(0);會區找當前進程的IO緩衝區,把裏面的內容取出打印出來
//_exit(0);不會打印出IO緩衝區的內容,直接退出進程
//printf的數據會先存入IO緩衝區,遇到\n才會從IO緩衝區取出數據打印到屏幕上
int main()
{
pid_t result;
result=fork();
if(result == -1)
printf("fork error!\r\n");
if(result == 0)
{
printf("son");
_exit(0);
}
else
{
printf("parent");
exit(0);
}
return 0;
}
结果:终端打印出parent 没有打印出son
二、void wait(int *status)
- wait(&status) : 写在父进程中等待子进程执行结束,但是这样写很粗暴,会阻塞父进程,一般是子进程退出时,发送一个信号通知给父线程,父线程接收到信号后,再使用WIFEXITED(status) 和 WEXITSTATUS(status) 获取子进程的退出值。
- WIFEXITED(status) :如果子进程正常退出,该值为真
- WEXITSTATUS(status):如果子进程退出正常,该宏能获取子进程的退出值
#include<stdio.h>
#include<sys/wait.h>
#include <unistd.h>
#include<stdlib.h>
int main()
{
pid_t result;
int status;
result = fork();
if(result == -1)
printf("error!\r\n");
if(result == 0)
{
printf("son\r\n");
exit(11);//退出值为11
}
else
{
printf("parent\r\n");
wait(&status);
if(WIFEXITED(status) == 1)
printf("exit value:%d\r\n",WEXITSTATUS(status));
三、进程的生老病死
进程状态(宏):
- TASK RUNNING:就绪运行状态 (运行)
- TASK_INTERRUPTIBLE:可中断睡眠状态 (睡眠)
- TASK_UNINTERRUPTIBLE:不可中断睡眠状态 (睡眠)
- TASK TRACED:调试态 (暂停)
- TASK_STOPPED:暂停状态 (暂停)
- EXIT_ZOMBIE:僵死状态 (僵尸)
- EXIT_DEAD;死亡态 (死亡)
前后台进程组
- 执行程序时加上 & 可让程序运行在后台,不占用终端 // 如./a.out &
- jobs 命令可查看后台进程组起他们的jobsID
- ctrl+z 可使前台进程转换为后台进程,并停止
- fg+jobsID 可使后台进程转换为前台进程
守护进程
- fork创建子进程,父进程直接退出// fork()
- 创建一个新的会话,摆脱终端的影响// setsid()
- 改变守护进程的当前工作目录,该为“/” //chdir();
- 重设文件权限掩码 //umask命令可查看文件权限掩码 umask(int)改变文件权限掩码
//文件默认权限 0666(8进制),umask:022 真正文件权限 066 &~ umask - 关闭不需要的文件描述符 0 1 2 即标椎输入 输出 错误 //close()
#include<stdio.h>
#include<sys/wait.h>
#include <unistd.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<fcntl.h>
#include <string.h>
int main()
{
pid_t pid;
int fd, len;
const char* buf = "the daemon is running\r\n";
len = strlen(buf);
if((pid = fork()) < 0)
{
printf("fork error\r\n");
exit(1);
}
else if(pid == 0)
{
setsid();
chdir("/");
umask(0);
for(int i=0;i<3;i++)
{
close(i);
}
while(1)
{
fd = open("/home/wzt/Code/system_programming/part_5/daemon1.log",O_CREAT|O_WRONLY|O_APPEND,0666);
if(fd < 0)
{
printf("open error\r\n");
}
write(fd, buf, len);
close(fd);
sleep(5);
}
}
else
{
exit(0);
}
return 0;
}
普通进程伪装成守护进程: nohup命令 // nohup sleep 100 &
僵尸进程
正常程序退出:
- 子进程用exit()函数退出
- 父进程调用wait()函数等待
僵尸进程:子进程退出后,父进程没有调用wait()函数处理身后事,子进程变成僵尸进程
托孤进程
- 父进程先于子进程退出,子进程变成孤儿进程,linux系统会孤儿进程托孤给init进程