教学文库网 - 权威文档分享云平台
您的当前位置:首页 > 精品文档 > 说明书 >

Linux内核设计与实现

来源:网络收集 时间:2026-08-23
导读: 进程管理 一、FORK()函数的两次返回的具体情况 对于fork来说,父子进程共享同一段代码空间,所以给人的感觉好像是有两次返回,其实对于调用 fork的父进程来说,如果fork出来的子进程没有得到调度,那么父进程从fork系统调用返回,同时分析sys_fork知道,fork

进程管理

一、FORK()函数的两次返回的具体情况

对于fork来说,父子进程共享同一段代码空间,所以给人的感觉好像是有两次返回,其实对于调用 fork的父进程来说,如果fork出来的子进程没有得到调度,那么父进程从fork系统调用返回,同时分析sys_fork知道,fork返回的是子进 程的id。再看fork出来的子进程,由copy_process函数可以看出,子进程的返回地址为ret_from_fork(和父进程在同一个代码点 上返回),返回值直接置为0。所以当子进程得到调度的时候,也从fork返回,返回值为0。

关键注意两点:1.fork返回后,父进程或子进程的执行位置。(首先会将当前进程eax的值做为返回值)2.两次返回的pid存放的位置。(eax中)

进程调用copy_process得到lastpid的值(放入eax中,fork正常返回后,父进程中返回的就是lastpid)

子进程任务状态段tss的eax被设置成0,

fork.c 中

p->tss.eax=0;(如果子进程要执行就需要进程切换,当发生切换时,子进程tss中的eax值就调入eax寄存器,子进程执行时首先会将eax的内容做为返回值)

当子进程开始执行时,copy_process返回eax的值。

fork()后,就是两个任务同时进行,父进程用他的tss,子进程用自己的tss,在切换时,各用各的eax中的值.

所以,“一次调用两次返回”是2个不同的进程!

例子:

int main()

{

pid_t pid;

pid=fork();

if ( pid < 0 ) {

fprintf( stderr, "Fork Failed" );

exit( -1 );

}

else

if ( pid == 0 ) {

printf( "child process\\n");

}

else

{

printf( "parent process\\n" );

}

return 0;

}

这个程序执行为什么总是显示:child process

parent process

而不会先是parent 后是child呢?

答:看这一句:pid=fork()

当 执行这一句时,当前进程进入fork()运行,此时,fork()内会用一段嵌入式汇编进行系统调用:int 0x80(具体代码可参见内核版本0.11的unistd.h文件的133行_syscall0函数)。这时进入内核根据此前写入eax的系统调用功能号 便会运行sys_fork系统调用。接着,sys_fork中首先会调用C函数find_empty_process产生一个新的进程,然后会调用C函数 copy_process将父进程的内容复制给子进程,但是子进程tss中的eax值赋值为0(这也是为什么子进程中返回0的原因),当赋值完成后, copy_process会返回新进程(该子进程)的linux进程描述符—task_struct结构

为了管理进程,操作系统必须对每个进程所做的事情进行清楚地描述,为此,操作系统使用数据结构来代表处理不同的实体,这个数据结构就是通常所说的进程描述符或进程控制块,在linux系统中,这就是task_struct结构,在include\linux\sched.h文件中定义。每个进程都会被分配一个task_struct结构,它包含了这个进程的所有信息,在任何时候操作系统都能跟踪这个结构的信息,这个结构是linux内核汇总最重要的数据结构,下面我们会详细的介绍。这个结构的源代码及其注释如下,之后对其进行了分类解释。

//进程描述符task_struct

struct task_struct {

/* * offsets of these are hardcoded elsewhere - touch with care

*/ volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ //-1 不能运行 0 运行 >0 停止

unsigned long flags; /* per process flags, defined below *///进程标志,在下面定义

int sigpending; //进程上是否有待处理的信号

mm_segment_t addr_limit; /* thread address space:进程地址空间

0-0xBFFFFFFF for user-thead

0-0xFFFFFFFF for kernel-thread

*/

volatile long need_resched; //调度标志,表示该进程是否需要重新调度,若非0,则当从

内核态返回到用户态,会发生调度

int lock_depth; /* Lock depth *///锁深度

/* * offset 32 begins here on 32-bit platforms. We keep

* all fields in a single cacheline that are needed for

* the goodness() loop in schedule().

*/ long counter; //进程可运行的时间量

long nice; //进程的基本时间片

unsigned long policy; //进程的调度策略,有三种,实时进程:SCHED_FIFO,SCHED_RR;分时进程:SCHED_OTHER;

struct mm_struct *mm; //进程内存管理信息

int processor;

/* * cpus_runnable is ~0 if the process is not running on any

* CPU. It's (1 << cpu) if it's running on a CPU. This mask

* is updated under the runqueue lock.

* * To determine whether a process might run on a CPU, this

* mask is AND-ed with cpus_allowed.

* 若进程不在任何CPU上运行,cpus_runnable 的值是0,否则是1。这个值在运行 *队列被锁时更新;*/

unsigned long cpus_runnable, cpus_allowed;

/* * (only the 'next' pointer fits into the cacheline, but

* that's just fine.)

*/

struct list_head run_list; //指向运行队列的指针

unsigned long sleep_time; //进程的睡眠时间

struct task_struct *next_task, *prev_task; //用于将系统中所有的进程连成一个双向循环链表,其根是init_task.

struct mm_struct *active_mm;

struct list_head local_pages; //指向本地页面

unsigned int allocation_order, nr_local_pages;

/* task state */

struct linux_binfmt *binfmt; //进程所运行的可执行文件的格式

int exit_code, exit_signal;

int pdeath_signal; /* The signal sent when the parent dies *///父进程终止是向子进程发送的信号

/* ??? */

unsigned long personality; //Linux可以运行由其他UNIX操作系统生成的符合iBCS2标准的程序

int did_exec:1; //按POSIX要求设计的布尔量,区分进程正在执行从父进程中继承的代码,还是执行由execve装入的新程序代码

pid_t pid; //进程标识符,用来代表一个进程

pid_t pgrp; //进程组标识,表示进程所属的进程组

pid_t tty_old_pgrp; //进程控制终端所在的组标识

pid_t session; //进程的会话标识

pid_t tgid;

/* boolean value for session group leader */

int leader; //标志,表示进程是否为会话主管

/*

* pointers to (original) parent process, youngest child, younger sibling,

* older sibling, respectively. (p->father can be replaced with

* p->p_pptr->pid)

*///指针指向 …… 此处隐藏:12632字,全部文档内容请下载后查看。喜欢就下载吧 ……

Linux内核设计与实现.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.jiaowen.net/wendang/1483138.html(转载请注明文章来源)
Copyright © 2020-2025 教文网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:78024566 邮箱:78024566@qq.com
苏ICP备19068818号-2
Top
× 游客快捷下载通道(下载后可以自由复制和排版)
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能出现无法下载或内容有问题,请联系客服协助您处理。
× 常见问题(客服时间:周一到周五 9:30-18:00)