进程
:程序的一个执行实例,正在运行的程序等,同时是分配系统资源的基本单位
描述进程(PCB):在linux环境下用task_struct的结构体来描述进程,该结构体包含了进程所需要的所有信息。
task_struct:是内核中linux下的一种数据结构,它会被装载在RAM下包含进程的信息。
内容分类:
标识符:进程的唯一标识符,区别于其他进程
状态:任务状态,退出代码,退出信号
优先级:此进程相比较其他进程的优先级
程序计数器:即将执行的下一条指令的地址
内存指针:包括程序代码以及和进程相关信息的指针,以及其他共享内存块的指针
上下文数据:进程执行时cpu中寄存器中的数据
I/O信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表
记账信息:辅助进程调度
进程状态
volatile long state//说明该进程是否可以执行,还是可中断等信息
#define TASK_RUNNING 0 //正在运行或者在就绪队列中准备运行的进程
#define TASK_INTERRUPTIBLE 1 //处于等待队列中的进程,直到某个条件有效时进入就绪队列
#define TASK_UNINTERRUPTIBLE 2 //处于等待队列中的进程,待资源有效时唤醒,不可由其他进程通过信号或定时中断唤醒
#define __TASK_STOPPED 4 //进程被暂停,通过其他进程的信号才能唤醒
#define __TASK_TRACED 8 //表示进程被Debug追踪
/* in tsk->exit_state */
#define EXIT_ZOMBIE 16 //僵尸状态的进程,表示进程被终止,但父进程还没获得其终止信息
#define EXIT_DEAD 32//进程死亡
/* in tsk->state again */
#define TASK_DEAD 64 //死亡
#define TASK_WAKEKILL 128 //唤醒并杀死进程
#define TASK_WAKING 256//唤醒进程
2.进程的标识符
pid_t pid;//进程的唯一标识符
pid_t tgid;//线程组的领头线程的pid
在linux环境下,一个线程组所有的线程使用和该线程组的领头线程相同的pid,并存放在tgid中。
进程的标记符
unsigned int flags;
flags反映进程的状态信息,用于内核识别该进程的当前状态
常用的状态
#define PF_FORKNOEXEC 0x00000040 //表示进程刚被创建,还没执行
#define PF_SUPERPRIV 0x00000100 //表示该进程有超级用户特权
#define PF_SIGNALED 0x00000400 //表示进程被信号杀出
#define PF_EXITING 0x00000004 //表示进程开始退出
进程之间的亲属关系
struct task_struct *real_parent;
struct task_struct *parent;
struct list_head children;
struct list_head sibling;
struct task_struct *group_leader;
real_parent指向其父进程,如果创建它的父进程不存在,则指向pid为1的init进程。
parent指向其父进程,当它终止时,必须向它父进程发出信号,值通常与real_parent相同。
children表示链表的头部,链表的所有元素都是其子进程。
sibling用于把当前进程插入到兄弟链表中。
group_leader指向其所在进程组的领头进程。
进程的调度信息
int prio,static_prio, normal_prio;
unsigned int rt_priority;
const struct sched_class *sched_class;
struct sched_entity se;
struct sched_rt_entity rt;
unsigned int policy;
stati_prio用于保存静态优先级,可以通过nice系统调用来进行修改
rt_priority用于保存实时优先级。
normal_prio的值取决于静态优先级和调度决策。
prio用于保存动态优先级。
policy表示进程的调度策略。
进程的调度算法
#define SCHED_NORMAL 0//按照优先级进行调度
#define SCHED_FIFO 1//先进先服务的调度算法
#define SCHED_RR 2//时间片轮转的调度算法
#define SCHED_BATCH 3//用于非交互的CPU消耗型的进程
#define SCHED_IDLE 5//系统负载很低时的调度
#define SCHED_RESET_ON_FORK 0x40000000
创建进程
我们分别可以用fork()和vfork()来创建进程,新创建的进程为子进程,原进程为父进程,代码实现如下
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
int ret=fork();
if(ret<0)
perror("fork");
return 1;
else if(ret==0)
{
printf("child:%d!,ret:%d\n",getpid(),ret);
}else{
printf("father:%d!,ret:%d\n",getpid(),ret);
}
sleep(1);
return 0;
}
僵尸进程:当进程退出,父进程没有接收到子进程退出信号
#include<stdio.h>
#include<stdlib.h>
int main()
{
pid_t id =fork();
if(id<0)
perror("fork");
return 1;
else if(id==0)
{
printf("child:%d is begin z\n",getpid());
sleep(5);
exit(EXIT_SUCCESS);
}
else{
printf("parent;%d is sleeping\n",getpid());
sleep(30);
}
return 0;
}
孤儿进程:父进程先退出,子进程称之为“孤儿进程”。
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t id =fork();
if(id<0)
{
perror("fork");
return 1;
}
else if(id==0)
{
printf("child,pid:%d\n",getpid());
sleep(10);
}
else
{
printf("parent,pid:%d\n",getpid());
sleep(3);
exit(0);
}
return 0;
}