本文主要探讨unix/linux进程的相关内容
进程的定义
狭义定义:进程是正在运行的程序的实例。
广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是动态执行的基本单元,在传统操作系统中,进程既是基本的分配单元,也是基本的执行单元。
进程的特点
动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
并发性:任何进程都可以同其他进程一起并发执行
独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
结构特征:进程由程序、数据和进程控制块三部分组成。
多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变
进程的状态
就绪状态:进程已获得除处理器外的所需资源,等待分配处理器资源;只要分配了处理器进程就可执行。就绪进程可以按多个优先级来划分队列。例如,当一个进程由于时间片用完而进入就绪状态时,排入低优先级队列;当进程由I/O操作完成而进入就绪状态时,排入高优先级队列
运行状态:进程占用处理器资源;处于此状态的进程的数目小于等于处理器的数目。在没有进程可以执行时,通常会自动执行系统的空闲进程
阻塞状态:由于进程等待某种条件,在条件满足之前无法继续执行。该事件发生前即使把处理器资源分配给该进程,也无法运行
创建进程
pid_t fork(void);
返回值:
>0 :父进程,0:子进程
等待子进程
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
wait:
参数
status:子进程退出状态码
返回值
成功执行返回子进pid,失败返回-1
waitpid:
参数
pid:
<-1 子进程组号pid绝对值。
-1 任何子进程。
0 进程组号等于调用进程的任何子进程。
>0 进程号为pid的子进程。
stuatus:子进程退出状态码
options:
WNOHANG 子进程没有结束,返回0,不等待。结束则返回子进程ID
WUNTRACED 子进程中止时也返回
WCONTINUED 中止子进程被SIGCONT唤醒时也返回
返回值
成功执行返回子进pid,失败返回-1
waitid:
参数
id_type:
idtype=P_PID:指定进程号的子进程。
idtype=P_PGID:指定进程组号的所有子进程。
idtype==P_ALL:所有子进程。
id:子进程pid
options:
WEXITED:终止的子进程
WSTOPPED:被信号暂停的子进程
WCONTINUED:由SIGCONT重新启动的子进程
WNOHANG:同wiatpid中的
WNOWAIT:等待的子进程返回,后续wait还可获取子进程的状态
infop:
si_pid: 子进程的进程id
si_uid:子进程的真实用户id
si_signo:总是设置为SIGCHID
si_status:子进程的返回状态,子进程状态改变信
返回值
成功执行返回子进pid,失败返回-1
wait相关函数的status判断
status,是int型指针,可以通过下面宏对结果判别:
WIFEXITED(status) 子进程正常终止返回的状态为真
WEXITSTATUS(status) 子进程 exit()返回的结束码,
先WIFEXITED判断是否正常退出
WIFSIGNALED(status)子进程被信号终止返回的状态为真
WTERMSIG(status)子进程终止的信号值,需要在WIFSIGNALED返
回值为真
WCOREDUMP(status)子进程产生核心转存返回真,需要
WIFSIGNALED返回值为真。
WIFSTOPPED(status)子进程没有终止,可以重新执行
时,该宏返回真
WSTOPSIG(status) WIFSTOPPED(status)返回真,该宏返回导致
子进程停止的信号(signal)值
demo1:
父子进程共用进程之外的空间
示例:(父子进程都可修改num的值)
#include <stdio.h>
#include <stdlib.h>
void result()
{
int f_id;
int son;
int father;
int num = 10;
f_id = fork();
if(f_id == 0)
{
while(1)
{
num = num + 1;
printf("son pid is %d,son num is %d\n",getpid(),num);
sleep(1);
}
}
else if(f_id > 0)
{
while(1)
{
num = num + 1;
printf("father pid is %d,father num is %d\n",getpid(),num);
sleep(1);
}
}
else
{
printf("create fork fail\n");
perror("why");
exit(-1);
}
}
int main()
{
result();
return 0;
}
结果示例:
demo2:
僵死进程产生
1)父进程未结束,子进程结束,并且父进程未获取子进程的退出状态。
2) 进程执行结束,进程主体都释放,而其PCB 并未释放。
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
void result()
{
int pid;
int n = 0;
int status;
pid = fork();
if(pid > 0)
{
waitpid(0,&status,WNOHANG);
while(1)
{
printf("father pid is %d\n",getpid());
sleep(1);
}
}
else if(pid == 0)
{
while(1)
{
printf("son pid is %d\n",getpid());
n++;
if(n == 3)
{
exit(-1);
}
sleep(1);
}
}
else
{
printf("create fork fail\n");
perror("why");
exit(-1);
}
}
int main()
{
result();
return 0;
}
结果示例
demo3:
孤儿进程
父进程不等子进程退出,提前结束进程,子进程为孤儿进程,子进程被systemd接
管,systemd的id为1
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
void result()
{
int pid;
int n = 0;
int status;
pid = fork();
if(pid > 0)
{
waitpid(0,&status,WNOHANG);
while(1)
{
printf("father pid is %d\n",getpid());
n++;
if(n == 3)
{
exit(-1);
}
sleep(1);
}
}
else if(pid == 0)
{
while(1)
{
printf("son pid is %d\n",getpid());
sleep(1);
}
}
else
{
printf("create fork fail\n");
perror("why");
exit(-1);
}
}
int
结果示例:
demo4:
父子进程正常结束,父进程接受并打印子进程退出码
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
void result()
{
int pid;
int n = 0;
int status;
pid = fork();
if(pid > 0)
{
wait(&status);
printf("father pid is %d,son exit status is %d\n",getpid(),WEXITSTATUS(status));
}
else if(pid == 0)
{
while(1)
{
printf("son pid is %d\n",getpid());
n++;
if(n == 3)
{
exit(1);
}
sleep(1);
}
}
else
{
printf("create fork fail\n");
perror("why");
exit(-1);
}
}
int main()
{
result();
return 0;
}
结果示例: