[Linux驱动入门]进程管理

来源:互联网 发布:in Linux system 编辑:程序博客网 时间:2024/06/10 22:22

第二章  进程管理

2.1 进程调度

    Linux提供抢占式多任务模式,进程在被抢占之前能够运行的时间叫进程的时间片,Linux独一无二的公平调度程序本身并没有采用时间片来达到公平调度。

进程分为I/O消耗型和处理器消耗型。前者指进程的大部分时间用来提交I/O请求或是等待I/O请求的;后者是指进程把事件大多数用在执行代码上。Linux更倾向于优先调度I/O消耗型进程。

Linux采用两种不同的优先级范围:第一种是nice值,越大的nice值意味着更低的优先级;第二种是实时优先级,其值可以配置,越高的实时优先级数值意味着进程优先级越高。

 

2.2 Linux调度的实现

(1)时间记账

(2)进程选择

(3)调度器入口

(4)睡眠和唤醒

 

2.3 抢占和上下文切换

   上下文切换是从一个可执行进程切换到另一个可执行进程。Schedule函数主要完成两个工作:其一,把虚拟内存从上一个进程映射切换到新进程中;其二,从上一个进程的处理器状态切换到新进程的处理器状态。

   内核中need_resched标志表明是否需要重新执行一次调度,该标志对于内核来讲是一个信息,它表示有其他进程应当被运行了,要尽快调用调度程序。

   用户抢占:内核即将返回用户空间的时候,如果need_resched标志被设置,会导致schedule函数被调用,此时会发生用户抢占。用户抢占一般在如下情况下发生:其一,从系统调用返回用户空间时;其二,从中断处理程序返回用户空间时。

   内核抢占:内核可以在任何时候抢占正在执行的任务。内核抢占一般在如下情况下发生:

(1)中断处理程序正在执行,且返回用户空间之前;

(2)内核代码再一次具有可抢占性的时候;

(3)如果内核中的任务显式地调用schedule函数;

(4)如果内核中的任务阻塞。

 

2.4 进程概念

   进程是正在执行的程序代码的实时结果,是处于执行期的程序以及相关的资源的总称。线程是在进程中活动的对象,内核调度的对象是线程,而不是进程。

   进程提供两种虚拟机制——虚拟处理器和虚拟内存。线程之间可以共享内存,但每个都拥有各自的虚拟处理器。

进程五种状态标志:TASK_RUNNING,TASK_INTERRUPTIBLE,TASK_UN INTERRUPTIBLE,TASK_TRACED,TASK_STOPPPED.

 

2.5 进程上下文

   程序在用户空间执行时,当一个程序执行了一个系统调用或者触发了某个异常,它就陷入内核空间,称为内核“代表进程执行”并处于进程上下文中。

 

2.6 进程与线程的创建

从现有内核线程中创建一个新的内核线程有两种方法:

(1)利用kthread_creat()函数创建,并用wake_up_process()唤醒;

(2)直接执行kthread_run().

内核线程启动之后就一直运行直到调用do_exit()退出,或者内核的其他部分调用kthread_stop()退出。

 

2.7 孤儿进程

    如果父进程在子进程之前退出,必须有一个机制来保证子进程能找到一个新父亲,否则这些孤儿进程就会在退出时永远处于僵死状态,白白耗费内存。

 

2.8 系统调用

系统调用是用户空间访问内核的唯一手段,除异常和陷入外,它们是内核唯一的合法入口。

定义一个系统调用:

asmlinkage  long  sys_test(void)

内核在执行系统调用的时候处于进程上下文,在进程上下文中,内核可以休眠,并且可以被抢占。系统调用返回的时候,控制权仍在system_call中,它最终负责切换到用户空间,并让用户继续执行下去。

 

2.9 内核设计系统调用

主要完成系统调用函数编写,系统调用号,系统调用表的填写。

步骤1:在“/include/linux/syscalls.h”中增加要添加的系统调用的声明。

asmlinkage long sys_test(void);

步骤2:在“/arch/arm/include/asm/unistd.h”

#define  _NR_test(_NR_SYSCALL_BASE+361)

步骤3:在“/kernel/sys.c”中实现系统调用函数。

asmlinkage long sys_test(void)

{

printk(pid: %d,this is test call.\n,current->pid);

return 0;

}

步骤4:在“/arch/arm/kernek/calls.S”中加入系统调用表的初始化部分

/* 361 */   CALL(sys_test)

步骤5:生成内核镜像。应用层测试程序。

#include <Linux/unisted.h>

#include <stdio.h>

#include <errno.h>

int main()

{

int i = 10;

i = syscall(361);

printf(after  syscall : i = %d\n,i);

return 0;

}

测试结果:

pid: 859,this is test call.

after syscalli = 0

 

 

 

0 0