zoukankan      html  css  js  c++  java
  • 【Linux开发】linux设备驱动归纳总结(四):1.进程管理的相关概念

    linux设备驱动归纳总结(四):1.进程管理的相关概念


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    接下来的几节我会大概的讲一下内核进程的一些概念,其实应该在学习系统编程时候就应该知道的。。我参照的书籍是《linux内核设计与实现》(第三版)。我会尽可能地跳开内核代码,简述一下原理。

    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    一、什么是进程


    简单的说,进程就是正在运行的程序,一个程序可以同时有多个进程。学过C语言都知道,程序运行时并不是只有代码,还包含其他的资源,如打开的文件,信号,全局变量等等。我在《操作系统原理》中看过一个很生动很深刻的例子:一个人对照着菜谱做菜。在这例子中,人就是内核,菜谱就是程序,做菜的过程就是进程,而菜、锅就是这个进程的资源。

    内核为线程提供了两种技术:虚拟处理器和虚拟内存。这就是说,每个进程都傻乎乎的认为自己独占着CPU和享用这4G的内存,确不知道内核在背后调度进程和给每个进程4G的虚拟地址。

    进程由fork创建,通过exit退出。

    有人或许会问,那线程是什么?线程就是一种特殊的进程。


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    二、进程是用什么结构体来维护


    内核将所有的进程放在叫任务队列(task list的双向循环链表中,链表中的每个项都是类型为task_struct、称为进程描述符的结构。每个进程描述符包含着一个进程的所有信息,驱动开发中我用得最频繁的有两个成员,pid(进程标识值)comm(当前进程的所执行的程序文件名称)。

    来张形象点的图:

    获得当前正在进行的进程进程描述符也很简单,使用全局项current就可以获得。

    /*4th_mutex/4th_mutex_1/1st/test.c*/

    113 P_DEBUG("[%s]:pid[%d] ", current->comm, current->pid);


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    三、进程的状态


    我只说5种,其中前两种是之前在等待队列的时候介绍过。

    1TASK_RUNNING(运行):该状态出现在进程正在运行,或者已经放在运行队列中等待执行(对应操作系统原理上所说的就绪状态)。这里要注意的是等待执行和休眠是两码事

    2TASK_INTERRUPTIBLE(可中断休眠):这就是休眠状态中一种,之所以说可中断,就是说除了可以被其他进程从等待队列唤醒以外,还可以接送到信号而唤醒,这是常用的休眠状态。

    3TASK_UNINTERRUPTIBLE(不可中断休眠):这就是休眠状态的另一种,只能从等待队列被唤醒。因为它如此霸道,所以很少有人使用。

    4TASK_ZOMBIE(僵死):这种情况出现在进程结束后,但父进程还有来回收该进程的进程描述符

    5TASK_STOPPED(停止):一看就知道,进程停止执行。


    来个图来对照前四种状态的转换:

    由上图可以看到用户空间的进程有fork()系统调用产生,如果运行途中没有任何阻塞,它会在最后调用do_exit将进程的状态转为TASK_ZOMBIE。等待父进程来收尸。接下来就要简单地说一下进程的创建和进程的终结


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    四、进程的创建

    进程的创建一般分两步:


    1、调用fork()

    在系统编程时,我们一般都是调用fork()来创建新的用户进程。

    先说一下传统的forl()的实现,传统的fork()被调用后,内核会拷贝父进程的所有资源给新建的子进程。要知道这是一个多愚蠢的操作,如果新建子进程是打算执行另一个新程序,之前的拷贝过程就白费了。

    出于这样的原因,linuxfork()有了写时拷贝(copy-on-write)技术。从字面上就能理解意思,父进程创建子进程后,他给子进程创建一个文件描述符,并且与子进程以只读方式共享原有的资源,只有在子进程或者父进程修改资源时,资源才会被复制。所以说,在不修改资源的情况下,fork()的实际开销就两样:

    1)复制父进程的页表给子进程。大家应该都知道,linux内存管理使用的页式管理,只要也就是说,只要把父进程的页表复制给子进程,子进程就能在页表中找到与父进程共享的4G虚拟地址了。

    2)为子进程创建唯一的进程描述符。这个就不用解释了,进程与进程描述符是一一对应的。


    fork具体调用的什么函数我就不详细说了,不过应该有这样的一个概念:

    fork->clone->do_fork()->copy_procrss

    fork()系统调用根据提供的参数调用clone(),然后clone()去调用do_fork(),其中do_fork中完成了创建的大部分操作,里面有一个主要的函数copy_process()


    2、调用exec()

    一般的,创建的子进程都不是为了完成父进程中的任务,而是需要执行新的任务。exec()的作用就是读取可执行文件并加载到地址空间开始运行,可以类比成命令”./xxxxx”如果fork()后子进程调用exec()执行新的代码,就不需要拷贝父进程的资源了。所以,一般fork()之后都是子进程先运行。


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    五、进程的终结:


    一般的,进程调用exit()结束进程。相应的,exit()是调用do_exit()进行删除进程的资源和改变进程状态等操作。


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    六、什么是进程上下文:


    用户态的应用程序执行系统调用时,它就会陷入内核空间,此时,我们称内核“代表进程执行”并处于进程上下文。简单的说,以我们之前写的驱动举例,当应用成调用open,他就会陷入内核调用驱动函数中的test_open,此时内核就 处于进程上下文了。

    值得一提的是,在进程上下文时,current始终有效,它还是指向应用层中的进程,所以在”1st”的例子中,tesp_open打印出来的进程号current->pid与应用层是一样的。


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    七、线程、进程和内核线程程又是怎么样的关系:


    线程,它是进程活动中的对象,最通俗的解释,一个进程里面可以有一个或者多个线程,它们共同享用进程的资源。

    内核线程,独立运行在内核空间的标准进程,但没有独立的运行空间,只运行在内核空间,但和普通进程一样被调度和抢占。

    总的来说,线程(又叫用户线程)和内核线程都是进程的特殊形式,它们的创建同样也是通过调用clone()它们和进程的最大区别在于它们没有独立的4G虚拟空间

    而线程和内核线程的区别就是:线程存在与用户态,内核线程存在与内核态。

    同时需要强调的是,进程是存在于用户态的。


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    八、总结:


    今天只是介绍了进程的一些基本的概念,为以后的进程调度、并发、竞态等理论打基础。


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    源代码: 4th_mutex_1.rar   

  • 相关阅读:
    EXTJS 4.2 资料 控件之checkboxgroup的用法(静态数据)
    EXTJS 4.2 资料 控件之Window窗体相关属性的用法
    EXTJS 4.2 资料 控件之textfield文本框加事件的用法
    Entity Framework 学习笔记(一)之数据模型 数据库
    EXTJS 4.2 资料 控件之checkboxgroup的用法(动态数据)
    EXTJS 4.2 资料 控件之Grid 列鼠标悬停提示
    Entity Framework 学习笔记(二)之数据模型 Model 使用过程
    EXTJS 4.2 资料 控件之radiogroup 的用法
    EXTJS API
    vue移动端弹框组件,vue-layer-mobile
  • 原文地址:https://www.cnblogs.com/huty/p/8518593.html
Copyright © 2011-2022 走看看