进程的数据结构和管理

1.  进程的内核描述

struct task_struct {

              /*----------------------- these are hardcoded - don't touch -----------------------*/

              long state; // 进程运行状态(-1不可运行,0可运行,>0以停止)

              long counter; // 任务运行时间片,递减到0是说明时间片用完

              long priority; // 任务运行优先数,刚开始是counter=priority

              long signal; // 任务的信号位图,信号值=偏移+1

              struct sigaction sigaction[32]; //信号执行属性结构,对应信号将要执行的操作和标志信息

              long blocked; // 信号屏蔽码

             /*----------------------------------- various fields--------------------------------- */

             int exit_code; // 任务退出码,当任务结束时其父进程会读取

             unsigned long start_code,end_code,end_data,brk,start_stack;

             // start_code 代码段起始的线性地址

             // end_code 代码段长度

             // end_data 代码段长度+数据段长度

             // brk 代码段长度+数据段长度+bss段长度

             // start_stack 堆栈段起始线性地址

              long pid,father,pgrp,session,leader;

             // pid 进程号

             // father 父进程号

            // pgrp 父进程组号

            // session 会话号

            // leader 会话首领

            unsigned short uid,euid,suid;

            // uid 用户标id

            // euid 有效用户id

            // suid 保存的用户id

            unsigned short gid,egid,sgid;

           // gid 组id

           // egid 有效组id

           // sgid 保存组id

           long alarm; // 报警定时值

           long utime,stime,cutime,cstime,start_time;

          // utime 用户态运行时间

          // stime 内核态运行时间

          // cutime 子进程用户态运行时间

          // cstime 子进程内核态运行时间

          // start_time 进程开始运行时刻

             unsigned short used_math; // 标志,是否使用了387协处理器

/* ----------------------------------file system info-------------------------------- */

              int tty; // 进程使用tty的子设备号,-1表示没有使用

              unsigned short umask; //文件创建属性屏蔽码

             struct m_inode * pwd; // 当前工作目录的i节点

             struct m_inode * root; // 根目录的i节点

             struct m_inode * executable; // 可执行文件的i节点

              unsigned long close_on_exec; // 执行时关闭文件句柄位图标志

              struct file * filp[NR_OPEN]; // 进程使用的文件

              /*------------------ ldt for this task 0 - zero 1 - cs 2 - ds&ss -------------------*/

             struct desc_struct ldt[3]; // 本任务的ldt表,0-空,1-代码段,2-数据和堆栈段

              /* ---------------------------------tss for this task ---------------------------------*/

              struct tss_struct tss; // TSS

};

2. 进程0的描述符信息

/* state etc */ { 0,15,15, /

/* signals */ 0,{{},},0, /

/* ec,brk... */ 0,0,0,0,0,0, /

/* pid etc.. */ 0,-1,0,0,0, /

/* uid etc */ 0,0,0,0,0,0, /

/* alarm */ 0,0,0,0,0,0, /

/* math */ 0, /

/* fs info */ -1,0022,NULL,NULL,NULL,0, /

/* filp */ {NULL,}, /

{ /

{0,0}, / // ldt第0项是空

/* ldt */ {0x9f,0xc0fa00}, / //代码段长640K,基地0,G=1,D=1,DPL=3,P=1,TYPE=0x0a

{0x9f,0xc0f200}, / //数据段长640K,基地0,G=1, D=1, DPL=3,P=1, TYPE=0x02

}, /

/*tss*/ {0,PAGE_SIZE+(long)&init_task,0x10,0,0,0,0,(long)&pg_dir,/

// esp0 = PAGE_SIZE+(long)&init_task 内核态堆栈指针初始化为页面最后

// ss0 = 0x10 内核态堆栈的段选择符,指向系统数据段描述符,进程0的进程控制

// 块和内核态堆栈都在system模块中

// cr3 = (long)&pg_dir 页目录表,其实linux0.11所有进程共享一个页目录表

0,0,0,0,0,0,0,0, /

0,0,0x17,0x17,0x17,0x17,0x17,0x17, /

_LDT(0),0x80000000, / // ldt表选择符指向gdt中的LDT0处

{} /

}

3. 进程的内存布局

processMMLayout

4. 进程控制相关函数

   1).   sys_fork(), 克隆一个进程;

   2).   sys_execve(), 加载一个可执行程序(换上新的代码);

   3).   sys_exit(),进程退出。释放内存, 将所有孩子过继给进程1, 释放当前使用的文件资源, 释放TTY,如果是会话首领则结束会话。

   4).  sys_waitpid(), 等待某进程退出;

 

5. 信号处理

    信号相当于软中断, 用于进程间通讯. CPU在执行每条指令的末端检测是否有硬件中断,而内核在进程从内核态返回时检测是否响应信号。

struct sigaction { // 信号响应结构体

             void (*sa_handler)(int); // 信号响应函数地址,相当与中断服务程序入口

             sigset_t sa_mask; // 进程正在处理当前信号时,可能需要屏蔽新的信号

                                        // 将要屏蔽的信息存在这里。

                                        // 通常是把当前正在处理的信号屏蔽调。进程对正在处理

                                        // 的信号肯定是允许的,通过设置这个变量来决定是否允许

                                        // 当前信号嵌套。

             int sa_flags; // 改变信号处理过程的信号集

             void (*sa_restorer)(void); // 恢复函数入口地址,用于清除用户堆栈

                                                           // 这个函数由libc提供,用户无法自行设置

};

/*****************************************************************************/

/* 功能:为信号注册新的响应函数  */

/* 该响应函数是临时的,调用过一次后就恢复成SIG_DFL  */

/* 参数:signum 指定的信号  */

/* handler 待注册的响应函数  */

/* restorer 恢复函数,libc提供  */

/* 返回:signum信号原先的响应函数  */

/*****************************************************************************/

int sys_signal(int signum, long handler, long restorer)

{

struct sigaction tmp;

// 信号值不在范围内,或者企图修改SIGKILL的响应函数,则出错

// SIGKILL是不能被屏蔽的,收到SIGKILL的进程必须退出,所以SIGKILL的

// 响应函数必须是SIG_DFL且不允许被修改

if (signum<1 || signum>32 || signum==SIGKILL)

return -1;

//下面4句创建新的响应结构体

tmp.sa_handler = (void (*)(int)) handler; // 填入新的响应函数句柄

tmp.sa_mask = 0; // 响应信号时不屏蔽任何信号

tmp.sa_flags = SA_ONESHOT | SA_NOMASK; // 新的响应函数使用一次后就恢复成

// SIG_DFL

tmp.sa_restorer = (void (*)(void)) restorer; // 转入恢复函数

handler = (long) current->sigaction[signum-1].sa_handler;  // 保持旧的响应函数

current->sigaction[signum-1] = tmp; // 装入新的响应结构

return handler; // 返回旧函数的句柄

}

/*****************************************************************************/

/* 功能:为信号转载响应机构体  */

/* 该响应结构体永远存在,知道该信号被再次装载  */

/* 参数:signum 指定的信号  */

/* action 待转入的响应结构体指针,这是用户空间中的逻辑地址  */

/* oldaction 用于返回旧的响应结构体,这是用户空间中的逻辑地址  */

/* 返回:0 成功 –1 出错  */

/*****************************************************************************/

int sys_sigaction(int signum, const struct sigaction * action,

struct sigaction * oldaction)

{

struct sigaction tmp;

if (signum<1 || signum>32 || signum==SIGKILL)

return -1;

// 取出旧的响应结构体,放入tmp中。

// 这里用的是“=”,因为tmp和current都在内核空间

tmp = current->sigaction[signum-1];

// 装入新的响应结构体action

// 这里不能用“=”,因为新结构体是用户定义,在用户空间。action指向的是

// 用户空间中的逻辑地址

get_new((char *) action,

(char *) (signum-1+current->sigaction));

// 如果oldaction不是空,则把旧的响应结构体保存在它指向的地址

// 同眼,oldaction也是用户空间中的逻辑地址,不能用“=”直接赋值

if (oldaction)

save_old((char *) &tmp,(char *) oldaction);

// 如果允许信号在自己的信号处理函数中收到,则清空屏蔽码

if (current->sigaction[signum-1].sa_flags & SA_NOMASK)

current->sigaction[signum-1].sa_mask = 0;

else // 否则屏蔽自己

current->sigaction[signum-1].sa_mask |= (1<<(signum-1));

return 0;

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值