1.进程的管理
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
#include <unistd.h>
#include <sys/types.h>
uid_t getuid(void);
uid_t geteuid(void);
- getpid() - 获取当前进程的编号,返回类型是pid_t类型
- getppid() - 获取当前进程父进程,返回类型是pid_t类型
- getuid()- 获取但前用户编号,返回类型是uid_t类型
- getgid() - 获取当前用户所在组的编号,返回类型是gid_t类型
注意:
其中pid_t类型本质上就是int类型
其中uid_t类型本质上是unsigned int 类型
其中之gid_t类型本质上上unsigned int 类型
注意:查看类型:
如:查看pid_t类型
cc -E .c -o .i => vi .i => /pid_t
1.2 进程的创建
(1)fork函数
#include <unistd.h>
pid_t fork(void);
函数功能:
主要用于以复制当前正在调用进程的方式创建新进程,其中新进程创建出来的进程叫子进程,当前正在调用的进程叫做父进程;
该函数成功调用时,父进程返回子进程的进程号,子进程返回0;该函数调用失败时,父进程返回-1,没有子进程;
注意:
使用fork函数创建子进程后,父子进程的执行先后次序由操作系统的调用算法决定;
(2)父子进程的执行方式
- a.对于fork函数调用之前的代码来说,父进程执行一次
- b.对于fork函数调用之后的代码来说,父子进程各自自行一次;
- c.对于fork函数调用的返回值来说,父子进程各自返回一个,其中父子进程返回子进程的进程号,子进程返回0;
(3)父子进程之间的关系
- a.父进程启动了子进程,父子进程同时执行,如果子进程先于父进程结束,会给父进程发信号,父进程负责回收子进程的资源;
- b.如果父进程先结束,则子进程就会变成固孤儿进程,此时子进程会变更父进程(一般认定init(1)为新的父进程,)init进程收养了孤儿进程,因此也叫做孤儿院进程
- c.如果子进程先结束,但由于各种原因,父进程没有收到子进程发来的信号,也就不能回收子进程的资源,此时子进程就会变成僵尸进程;
(4)父子进程之间的复制关系
- 使用fork函数创建子进程后,子进程会父子父进程中除了代码区之外的其他内存区域,而代码区和父进程共享;
- 使用fork函数创建子进程后,子进程会复制父进程中的文件描述符总表,但不会复制文件等数据结构,因此父子进程对应的是同一个文件表结构
(5)扩展
a.如何创建3个新进程总共变成4个进程???
fork();
fork();
4个进程:1个父进程 + 2个子进程 + 1个孙子进程
b.如何创建2个新进程总共变成3个进程???
pid_t pid = fork();
if(pid > 0){
fork();
}
3个进程:1个父进程 + 2个子进程
c.俗称“fork炸弹”
while(1)
{
fork;
}//进程成指数形势增长
1.3进程的终止
(1)正常终止进程的方式
a.执行了main函数中的return语句;
b.调用exit函数终止进程;
c.调用_exit()/_Exit()函数终止进程中;
d.最后一个线程返回;
e.最后一个线程调用了pthread_exit()函数;
(2)非正常终止进程的方式
a.采用信号终止进程;
b.最后一个线程被其他线程取消
(3)相关函数的解析
#include <unistd.h>
void _exit(int status); - UC函数
#include <stdlib.h>
void _Exit(int status); - 标C函数
函数功能:
主要用于立即终止当前正在运行/调用的进程,在终止的同时,会关闭所有属于该进程的文件描述符;让该进程的所有子进程变更父进程为init进程;
给该进程的父进程发送SIGCHLD信号;
参数status的参数主要用于返回给父进程作为当前进程的退出状态信息,若父进程想要获取该推出状态信息,则需要调用wait系列函数中的一个;
The function _Exit() is equivalent to _exit().
>
#include <stdlib.h>
void exit(int status);
函数功能:
主要用于引起正常进程的终止,参数status & 0377 的结果会被返回给父进程,作为当前进程的退出状态信息,父进程若要获取该信息,也得调用wait系列函数中的一个
该函数在终止进程时会引起atexit()函数和on_exit()函数所注册(单独保存)函数的调用;
>
#include
1.4进程的等待
(1)wait()函数
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
函数功能:
主要用于挂起当前正在调用进程的执行,直到该进程中的任意一个子进程终止为止;
当参数不为空时,该函数会将获取到的退出状态信息填充到该参数指定的int类型存储空间中;
为了正确解析该退出状态信息,需要使用以下的带参宏:
WIFEXITED(*status) - 判断子进程是否正常终止,正常终止的方式有:调用_exit()/exit()/_Eexit()/执行了main函数中的return;
WEXITSTATUS(*status) - 获取子进程的退出状态信息;
成功返回终止子进程的进程号,失败返回-1;
(2) waitpid函数
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
第一个参数:进程的编号
-1 表示等待任意一个子进程状态发生改变
>0 表示等待进程号为pid的子进程状态发生改变
第二个参数:指针类型参数获取子进程的退出状态信息;
第三个参数:等待的方式goren给0 即可
返回值:成功返回终止子进程的进程号,失败返回-1;
函数功能:
主要用于等待参数指定的子进程转态发生改变;
The call wait(&status) is equivalent to : waitpid(-1, &status, 0);
练习:
vi 05file.c文件,首先创建/清空一个文件a.txt然后使用fork函数是创建子进程,再让父子进程分别写入”hello”和“world”最后关闭文件,
观察文件的执行结果
练习:
vi 07waitpid.文件,首先创建两个子进程,子进程一先开始执行,睡眠10秒后终止,调用exit(100);然后子进程2开始执行,睡眠的20秒后终止,
调用exit(200);父进程等待任意一个子进程终止,并获取退出状态信息,最后打印出来;