1、进程的由来
程序
静态文件
进程
运行着的实体
查看进程之间的关系
pstree
操作系统如何区分进程
PID:进程的身份证
ps -ef | more
q 来退出命令
2、创建一个新进程
fork函数
头文件:
#include <unistd.h>c
函数原型:
pid_t fork(void);
返回值:
成功 :0或其他正整数
失败:-1
fork函数特性
-
执行fork函数之后,fork函数会返回两次
-
在旧进程中返回时,返回值为0
-
在新进程返回时,返回值为进程的pid
叫做复制一个进程更加贴切
fork函数要点总结
在执行fork函数之前,操作系统只有一个进程,fork函数之前的代码只会被执行一次。
在执行fork函数之后,操作系统有两个几乎一样的进程,fork函数之后的代码会被执行两次。
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t i;
printf("before fork!\r\n");
i = fork();
printf("after fork:i=$d\r\n",i);
return 0;
}
执行命令:
3、子进程偷梁换柱
exec函数族
常用后缀:
l:代表以列表形式传参(list)
v:代表以矢量数组形式传参(vector)
p:代表使用环境变量Path来寻找指定执行文件
e:代表用户提供自定义的环境变量
头文件:
#include <unistd.h>
函数原型:
int execl(const char *path, const char *arg, ...)
运行代码:
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t result;
result = fork();
if (result > 0)
{
execl("/bin/ls", "ls", "-l",NULL);
printf("error!!\r\n");
return -1;
}
return 0;
}
运行结果:
总用量 24
-rw-rw-r-- 1 xiaolei xiaolei 1936 3月 21 10:24 execl.o
-rwxrwxr-x 1 xiaolei xiaolei 16784 3月 21 10:24 test_execl
int execlp(const char *file, const char *arg, ...)
运行代码:
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t result;
result = fork();
if (result > 0)
{
execlp("ls", "ls", "-l",NULL);
printf("error!!\r\n");
return -1;
}
return 0;
}
运行结果:
总用量 12
drwxrwxr-x 2 xiaolei xiaolei 4096 3月 21 10:44 build
-rw-rw-r-- 1 xiaolei xiaolei 198 3月 21 10:43 execlp.c
-rwxrwxr-x 1 xiaolei xiaolei 677 3月 21 10:44 makefile
int execv(const char *path, char *const argv[])
运行代码:
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t result;
char *arg[]={"ls","-l",NULL};
result = fork();
if (result > 0)
{
execv("/bin/ls",arg);
printf("error!!\r\n");
return -1;
}
return 0;
}
运行结果:
总用量 12
drwxrwxr-x 2 xiaolei xiaolei 4096 3月 21 10:51 build
-rw-rw-r-- 1 xiaolei xiaolei 220 3月 21 10:51 execv.c
-rwxrwxr-x 1 xiaolei xiaolei 676 3月 21 10:51 makefile
int execve(const char *path, char *const argv[],char *const envp[])
运行代码:
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t result;
char *arg[]={"env",NULL};
char *env[]={"PATH=/tmp","name=xiaolei",NULL};
result = fork();
if (result > 0)
{
execve("/usr/bin/env",arg,env);
printf("error!!\r\n");
return -1;
}
return 0;
}
运行结果:
PATH=/tmp
name=xiaolei
返回值:
成功:不返回
失败:-1
要点总结
-
l后缀和v后缀必须两者选其一来使用
-
p后缀和e后缀是可选的,可用可不用
-
组合后缀的相关函数还有很多,可自己进一步了解
exce函数有可能执行失败,需要预防
- 新程序的文件路径出错
- 传参或者是自定义环境变量时,没有加NULL
- 新程序没有执行权限
4、进程的退出
正常退出:
- 从main函数return
- 调用exit()函数终止
- 调用_exit()函数终止
exit和_exit退出函数
头文件:
#include <unistd.h>
#include <stdlib.h>
原型:
void _exit(int status);
void exit(int status);
返回值:
不返回
5、等待子进程的终结
wait函数
头文件
#include <sys/wait.h>
函数原型
pid_t wait(int *status)
返回值
- 成功:退出的子进程的pid
- 失败:-1
处理子进程退出状态值的宏
- WIFEXITED(status) :如果子进程正常退出,则该宏为真
- WEXITSTATUS(status):如果子进程正常.退出,则该宏获取子进程的退出值
6、进程的"生老病死"
进程状态:
- TASK_RUNNING:就绪/运行状态
- TASK_INTERRUPTIBLE:可中断睡眠状态
- TASK_UNINTERRUPTIBLE:不可中断睡眠状态
- TASK_TRACED:调试态
- TASK_STOPPED:暂停状态
- EXIT_ZOMBIE:僵死状态
- EXIT_DEAD:死亡态