一 进程与线程

进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源。

线程是进程中活动的对象,每个线程都拥有独立的程序计数器、进程栈和一组进程寄存器。

内核调度的对象是线程而不是进程。对Linux而言,线程是特殊的进程。

二 进程描述符及任务结构

内核使用双向循环链表的任务队列来存放进程,使用结构体task_struct来描述进程所有信息。

1 进程描述符task_struct

struct task_struct {}结构体相当大,大约1.7K字节。大概列出一些看看:

    

2 分配进程描述符

  当进程由于中断或系统调用从用户态转换到内核态时,进程所使用的栈也要从用户栈切换到内核栈。

通过内核栈获取栈尾thread_info,就可以获取当前进程描述符task_struct。

每个进程的thread_info结构在他的内核栈的尾端分配。结构中task域中存放是指向该任务实际的task_struct。

    

内核处理进程就是通过进程描述符task_struct结构体对象来操作。所以操作进程要获取当前正在运行的进程描述符。

通过thread_info的地址就可以找到task_struct地址;在不同的体系结构上计算thread_info的偏移地址不同。

/* linux-2.6.38.8/arch/arm/include/asm/current.h */
static inline struct task_struct *get_current(void)
{
return current_thread_info()->task;
} #define current (get_current())
/* linux-2.6.38.8/arch/arm/include/asm/thread_info.h */
static inline struct thread_info *current_thread_info(void)
{
   //栈指针
register unsigned long sp asm ("sp");
return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
}

3 进程的状态

系统中的每个进程都必然处于五种进程状态中的一种或进行切换。该域的值也必为下列五种状态标志之一:

TASK_RUNNING(运行)—进程是可执行的;它或者正在执行,或者在运行队列中等待执行(运行队列将会在第4章中讨论)。

这是进程在用户空间中执行的唯一可能的状态;这种状态也可以应用到内核空间中正在执行的进程。

TASK_INTERRUPTIBLE(可中断)—进程正在睡眠(也就是说它被阻塞),等待某些条件的达成。一旦这些条件达成,

内核就会把进程状态设置为运行。处于此状态的进程也会因为接收到信号而提前被唤醒并随时准备投入运行。

TASK_UNINTERRUPTIBLE(不可中断)—除了就算是接收到信号也不会被唤醒或准备投入运行外,这个状态与可打断状态相同。

这个状态通常在进程必须在等待时不受干扰或等待事件很快就会发生时出现。由于处于此状态的任务对信号不做响应,

所以较之可中断状态,使用得较少。

__TASK_TRACED—被其他进程跟踪的进程,例如通过ptrace对调试程序进行跟踪。

__TASK_STOPPED(停止)—进程停止执行;进程没有投入运行也不能投入运行。通常这种状态发生在接收到SIGSTOP、

SIGTSTP、SIGTTIN、SIGTTOU等信号的时候。此外,在调试期间接收到任何信号,都会使进程进入这种状态。

三 进程创建

fork: copy当前进程创建一个新的进程;

exec:读取可执行文件并将其载入地址空间开始运行。

1 fork过程

创建进程都是通过调用do_fork函数完成,其中提供了很多参数标志来表明进程创建的方式。

long do_fork(unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr) {
struct task_struct *p;
…… //创建进程
p = copy_process(clone_flags, stack_start, regs, stack_size,
child_tidptr, NULL, trace);
……
//将进程加入到运行队列中
wake_up_new_task(p);
}

copy_process里面通过父进程创建子进程,并未执行:

task_struct *copy_process(unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *child_tidptr,
struct pid *pid,
int trace) {
struct task_struct *p;
//创建进程内核栈和进程描述符
p = dup_task_struct(current); //得到的进程与父进程内容完全一致,初始化新创建进程
……
return p;
}

dup_task_struct根据父进程创建子进程内核栈和进程描述符:

static struct task_struct *dup_task_struct(struct task_struct *orig)
{
struct task_struct *tsk;
struct thread_info *ti;
int node = tsk_fork_get_node(orig); //创建进程描述符对象
tsk = alloc_task_struct_node(node);
//创建进程内核栈 thread_info
ti = alloc_thread_info_node(tsk, node); //使子进程描述符和父进程一致
err = arch_dup_task_struct(tsk, orig); //进程描述符stack指向thread_info
tsk->stack = ti; //使子进程thread_info内容与父进程一致但task指向子进程task_struct
setup_thread_stack(tsk, orig); return tsk; }

创建进程copy_process之后并未执行,返回到do_fork中,将新创建进程加入到运行队列中等待被执行。

四 线程在Linux中的实现与内核线程

线程机制提供了在同一个程序共享内存地址空间,文件等资源的一组线程。在Linux内核中把所有线程都当做进程来实现。

内核并没有提供调度算法,或者数据结构来表征线程,而是作为与其他进程共享资源的进程;与其他系统不同。

内核线程与普通进程间的区别是:

内核线程没有独立的地址空间

只在内核空间运行,不会切换到用户空间

五 进程终结

进程终结时内核释放其所占有的资源,并告诉父进程,更新父子关系。调用exit终结进程,进程被终结时通常最后都要调用do_exit来处理。

void do_exit(long code)
{
//获取当前运行进程
struct task_struct *tsk = current;
…… //sets PF_EXITING
exit_signals(tsk); //释放task_struct的mm_struct内存
exit_mm(tsk); //退出接收IPC信号队列
exit_sem(tsk); //进程名字空间
exit_shm(tsk); //文件描述符
exit_files(tsk); //文件系统
exit_fs(tsk); //资源释放
exit_thread(); //向父进程发送信号
exit_notify(tsk, group_dead);
…… //切换到其他进程
tsk->state = TASK_DEAD;
tsk->flags |= PF_NOFREEZE;
schedule();
……
}

(笔记)Linux内核学习(二)之进程的更多相关文章

  1. (笔记)Linux内核学习(九)之内核内存管理方式

    一 页 内核把物理页作为内存管理的基本单位:内存管理单元(MMU)把虚拟地址转换为物理 地址,通常以页为单位进行处理.MMU以页大小为单位来管理系统中的也表. 32位系统:页大小4KB 64位系统:页 ...

  2. (笔记)Linux内核学习(四)之系统调用

    一 用户空间和内核空间 Linux内核将这4G字节虚拟地址空间的空间分为两部分: l  将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为“内核空间”. l  ...

  3. linux内核学习之四:进程切换简述

    在讲述专业知识前,先讲讲我学习linux内核使用的入门书籍:<深入理解linux内核>第三版(英文原版叫<Understanding the Linux Kernel>),不过 ...

  4. linux内核学习之四:进程切换简述【转】

    转自:http://www.cnblogs.com/xiongyuanxiong/p/3531884.html 在讲述专业知识前,先讲讲我学习linux内核使用的入门书籍:<深入理解linux内 ...

  5. (笔记)Linux内核学习(一)之内核介绍

    内核与操作系统: 内核是操作系统的核心部分,包含了系统运行的核心过程,决定系统的性能,操作系统启动内核被装入到RAM中: 操作系统与底层硬件设备交互和为运行应用程序提供执行环境. Linux内核与微内 ...

  6. (笔记)Linux内核学习(三)之进程调度

    进程调度: 在可运行态进程之间分配有限处理器时间资源的内核子系统. 一 调度策略 1 进程类型 I/O消耗型进程:大部分时间用来提交I/O请求或是等待I/O请求,经常处于可运行状态,但运行时间短,等待 ...

  7. (笔记)Linux内核学习(十一)之I/O层和I/O调度机制

    一 块I/O基本概念 字符设备:按照字符流的方式被有序访问的设备.如串口.键盘等. 块设备:系统中不能随机(不需要按顺序)访问固定大小的数据片(chunk 块)的设备. 如:硬盘.软盘.CD-ROM驱 ...

  8. (笔记)Linux内核学习(八)之定时器和时间管理

    一 内核中的时间观念 内核在硬件的帮助下计算和管理时间.硬件为内核提供一个系统定时器用以计算流逝的时间.系 统定时器以某种频率自行触发,产生时钟中断,进入内核时钟中断处理程序中进行处理. 墙上时间和系 ...

  9. (笔记)Linux内核学习(十)之虚拟文件系统概念

    虚拟文件系统 虚拟文件系统:内核子系统VFS,VFS是内核中文件系统的抽象层,为用户空间提供文件系统相关接口: 通过虚拟文件系统,程序可以利用标准Linux文件系统调用在不同的文件系统中进行交互和操作 ...

随机推荐

  1. Microsoft Corporation 去掉 windows 修改 启动加载 版权

    windows 修改 开机界面 boot启动界面 windows 修改 启动加载 版权 windows 系统如何修改开机画面的版权文字“Microsoft Corporation ... ◎Micro ...

  2. phpstorm在项目中查找某个字符串

    如果项目过大,想在整个项目中找某个字符串,又不知道该字符串所在文件的路径,这时候就可以使用全局搜索了,ctrl+shift+F.在mac下,快捷键是command+shift+F:    

  3. 利用dockerfile定制镜像

    利用dockerfile定制镜像 镜像的定制就是定制每一层所添加的配置.文件.如果可以吧每一层修改.安装.构建.操作的命令都写入到一个脚本,用脚本来构建.定制镜像,这个脚本就是dockerfile. ...

  4. AJAX传输——以XML文件传输为例

    此文档解决以下问题: 一.responseText获取数据 1.AJAX异步传输,get请求方式/post请求方式,输出全部xml数据 二.responseXML获取数据 2.AJAX异步传输,get ...

  5. Android中POST请求代码

    public static String getDataByPost(String APIUrl,Map<String, String> paramsHashMap){ String re ...

  6. delphi StringGrid 表格的复制粘贴

    //参考如下代码--uses Clipbrd; function StringGridSelectText(mStringGrid: TStringGrid): string;var  I, J: I ...

  7. Unity Shader-后处理:简单均值模糊

    一.简介   今天来学习一下后处理中比较常用的一种效果,屏幕模糊效果.模糊效果,在图像处理中经常用到,Photoshop中也有类似的滤镜.我们在游戏中也会经常用到.因为屏幕模糊效果是一些高级后处理效果 ...

  8. boost.xml_parser中文字符问题 (转)

    当使用xml_parser进行读xml时,如果遇到中文字符会出现解析错误. 网上有解决方案说使用wptree来实现,但当使用wptree来写xml时也会出错.而使用ptree来写中文时不会出错. 综合 ...

  9. jQuery应用一之验证插件validate的使用

    综述 validate是一个用来验证表单提交的插件,应用十分广泛,具有如下的几个功能 自带了基本的验证规则 提供了丰富的验证信息提示功能 多种事件触发验证 自定义验证规则 下面我们就来感受一下这个插件 ...

  10. ECharts的geojson地图数据下载(根据城市区划代码的前六位查询)

    链接如下: http://echarts.baidu.com/echarts2/doc/example/geoJson/china-main-city/522200.json 想要对应城市的geojs ...