精华内容
下载资源
问答
  • 2012-08-22 09:40:56

    前面说从认识task_struct开始学习内核,今天又能了解里面的几个域了。

    一。进程链表

    每个task_struct中都有一个tasks的域来连接到进程链表上去。

    struct task_struct{
      ...
      struct list_head tasks;
      ...
      char comm[TASK_COMM_LEN];//可执行程序名
      ...
    };

    而这个链表的头是init_task.它是0号进程的PCB,0号进程永远不会被撤销,它被静态的分配到内核数据段上。也就是Init_task的PCB是由编译器预先分配的,在程序运行的过程中一直存在,直到程序结束。

     struct task_struct init_task = INIT_TASK(init_task);


    可以编写以下内核模块,得到所有进程的pid和进程名,并统计出进程总数。

    #include<linux/kernel.h>
    #include<linux/init.h>
    #include<linux/module.h>
    #include<linux/sched.h>
    
    MODULE_LICENSE("GPL");
    
    static int __init print_pid_init(void)
    {
    	struct task_struct *task,*p;
    	struct list_head *pos;
    	int count = 0;
    	printk("Begin to print process :\n");
    	task = &init_task;
    	list_for_each(pos,&task->tasks)
    	{
    		p = list_entry(pos,struct task_struct,tasks);
                    count++;
    		printk("%d ======> %s\n",p->pid,p->comm);
    	}
    	printk("the number of process is %d\n",count);
    	return 0;
    }
    static void __exit print_pid_exit(void)
    {
    	printk("End to print process.\n");
    }
    module_init(print_pid_init);
    module_exit(print_pid_exit);
    二。哈希表

    由于进程链表是将所有的进程连接到一个链表上去,所以查找一个进程的时间复杂度是O(N),是相当的低效。为此,使用哈希表来提高查找的效率。

    1.哈希表的定义

    我是在2.6.32.27内核中找到的,较老的版本可能是一个数组。

    static struct hlist_head *pid_hash;
    

    2.哈希函数

    学过数据结构的应该知道,哈希函数对整个查找是至关重要的,它决定了发生冲突的概率。好的哈希函数能够得到减少冲突。

    #define pid_hashfn(nr, ns)      \
            hash_long((unsigned long)nr + (unsigned long)ns, pidhash_shift)
    

     #define hash_long(val, bits) hash_32(val, bits)

    static inline u32 hash_32(u32 val, unsigned int bits)
    {
            /* On some cpus multiply is faster, on others gcc will do shifts */
            u32 hash = val * GOLDEN_RATIO_PRIME_32;
    
            /* High bits are more random, so use them. */
            return hash >> (32 - bits);
    }
    

    /* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
    #define GOLDEN_RATIO_PRIME_32 0x9e370001UL
    
    3.通过pid查找task_struct

    内核并不能直接通过pid找到对应的task_struct,而是先通过pid找到对应的struct pid,在通过struct pid 找到对应的task_struct。

    下面是详细介绍这两个的链接:

    i,pid到struct pid内核函数详解

    ii.struct pid 到task_struct的内核函数详解

    三。就绪队列

    与进程链表类似,task_struct也定义了一个连接到就绪队列的域run_list

    struct sched_rt_entity {
            struct list_head run_list;
            ....
    };
    struct task_struct
    { 
            ....
            struct sched_rt_entity rt;
            ......
    };
    

    就绪队列头:

    同样,内核中有一个就绪队列头runqueue_head

    四.等待队列

    1.等待队列的数据结构

    typedef struct __wait_queue wait_queue_t;
    struct __wait_queue {
            unsigned int flags;
    #define WQ_FLAG_EXCLUSIVE       0x01
            void *private;
            wait_queue_func_t func;
            struct list_head task_list;
    };
    
    task_list链接到等待队列上去。

    func是一个函数指针,指向唤醒等待队列中进程的函数。prviate是传递给func的参数,用于指定所要唤醒的进程。

    typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key);
    flags标志进程是否互斥: flags为WQ_FLAG_EXCLUSIVE  时互斥,否则,非互斥。

    2.等待队列头

    struct __wait_queue_head {
            spinlock_t lock;
            struct list_head task_list;
    };
    typedef struct __wait_queue_head wait_queue_head_t;

    因为等待队列是由中断处理程序和主要的内核函数修改的,因此要避免被同时访问。lock自旋锁对其进行同步,避免了双向链表被同时访问。task_list是双向链表的节点。

    3.等待队列的操作

    i.初始化

    首先,使用了下面的宏声明并初始化了一个等待队列头

    #define __WAIT_QUEUE_HEAD_INITIALIZER(name) {                           \
            .lock           = __SPIN_LOCK_UNLOCKED(name.lock),              \
            .task_list      = { &(name).task_list, &(name).task_list } }
    
    #define DECLARE_WAIT_QUEUE_HEAD(name) \
            wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
    如果要对列中一个元素初始化,要使用这个函数:

    static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
    {
            q->flags = 0;
            q->private = p;
            q->func = default_wake_function;//default_wake_function能够唤醒睡眠的进程p,并将其从等待队列中删除。
    }
    
    ii.插入/删除

    add_wait_queue()将一个非互斥进程插入到等待队列的第一个位置

    void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
    {
            unsigned long flags;
    
            wait->flags &= ~WQ_FLAG_EXCLUSIVE;
            spin_lock_irqsave(&q->lock, flags);
            __add_wait_queue(q, wait);
            spin_unlock_irqrestore(&q->lock, flags);
    }
    

    add_wait_queue_exclusive()将一个互斥进程插入到等待队列的最后一个位置

    void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait)
    {
            unsigned long flags;
    
            wait->flags |= WQ_FLAG_EXCLUSIVE;
            spin_lock_irqsave(&q->lock, flags);
            __add_wait_queue_tail(q, wait);
            spin_unlock_irqrestore(&q->lock, flags);
    }
    

    之所以将非互斥进程放在队首,而将互斥进程放在队尾,大概是因为非互斥进程不需要临界资源,将它唤醒不会影响其它进程的执行,而互斥进程得到临界资源会导致别的进程无法执行。

    remove_wait_queue()将一个进程从等待队列中删除。

    void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
    {
            unsigned long flags;
    
            spin_lock_irqsave(&q->lock, flags);
            __remove_wait_queue(q, wait);
            spin_unlock_irqrestore(&q->lock, flags);
    }
    
    iii.检查是否为空队列,直接调用了list.h中的list_empty()

    static inline int waitqueue_active(wait_queue_head_t *q)
    {               
            return !list_empty(&q->task_list);
    }
    
    iv.睡眠

    sleep_on_common(wait_queue_head_t *q, int state, long timeout)
    {
            unsigned long flags;
            wait_queue_t wait; 
    
            init_waitqueue_entry(&wait, current);
    
            __set_current_state(state);
    
            spin_lock_irqsave(&q->lock, flags);
            __add_wait_queue(q, &wait);
            spin_unlock(&q->lock);
            timeout = schedule_timeout(timeout);
            spin_lock_irq(&q->lock);
            __remove_wait_queue(q, &wait);
            spin_unlock_irqrestore(&q->lock, flags);
    
            return timeout;
    }
    

    v.唤醒

    static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
                            int nr_exclusive, int wake_flags, void *key)
    {
            wait_queue_t *curr, *next;
    
            list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
                    unsigned flags = curr->flags;
    
                    if (curr->func(curr, mode, wake_flags, key) &&
                                    (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
                            break;
            }
    }
    


    《----------------------完结------------》





    更多相关内容
  • - 进程的定义和三大组成 - 进程的两种组织形式 - 进程的五大特征

    进程的定义、组成、组织方式和特征

    视频链接地址:
    https://www.bilibili.com/video/BV1YE411D7nH/?spm_id_from=333.788.videocard.2
    

    前言

    在本篇中,你将掌握

    • 进程的定义和三大组成
    • 进程的两种组织形式
    • 进程的五大特征

    在这里插入图片描述

    1 进程的定义和组成

    程序:就是一个指令序列

    早期的计算机是只支持单道程序的,即CPU、内存、I/O设备只为当前的一道程序运行,在内存中程序的代码存放在程序段,程序运行过程处理的数据放在数据段内(如变量)。
    在这里插入图片描述
    引入多道程序技术之后,多道程序并发执行,内存中也就有了多段的程序段+数据段。也因此有了这样的问题,内存中同时放入多道程序,各个程序的代码、运算数据存放的位置不同、操作系统怎么才能找到各程序的存放位置呢?
      为了方便操作系统管理,完成各程序并发执行,引入了进程、进程实体的概念。系统为每个运行的程序配置了一个数据结构,称为进程控制块(PCB),用来描述进程的各种信息(如程序代码存放位置)。
    在这里插入图片描述

    进程的定义与组成

    PCB、程序段、数据段这三部分构成了进程实体(进程映像)。一般情况下,我们把进程实体就简称为进程。创建、撤销进程实质上就是PCB的创建和撤销。

    若要求区分进程和进程实体,则进程进程实体的运行过程,是系统进行资源分配调度的一个独立单位,进程是动态的过程,进程实体是静态的数据。若不区分,进程就是进程实体的简称。

    在这里插入图片描述
    值得注意的是,对于PCB、程序段、数据段来说,我们只需记住:

    1. 进程的管理者(操作系统)所需的数据都在PCB
    2. 程序本身的运行所需的数据都在程序段和数据段

    2 进程的组织

    在这里插入图片描述
    在系统中可能会有很多个进程,也就有多个PCB,为了组织管理如此多的PCB。有这样两种进程的组织方式:链接方式和索引方式

    1. 链接方式:队列

    在这里插入图片描述

    1. 索引方式:索引表
      在这里插入图片描述

    3 进程的特征

    在这里插入图片描述
    进程有五大特征:

    1. 动态性:进程是程序的一次执行过程
    2. 并发性:内存中有多个进程实体,各进程并发执行
    3. 独立性:进程是独立运行、独立获得资源、独立接受调度的基本单位(进程是资源分配、接受调度的基本单位
    4. 异步性:各进程按各自独立、不可预知的速度向前推进,操作系统要提供“进程同步机制”来解决异步问题
    5. 结构性:进程实体由程序段、数据段和PCB组成

    4 小结

    在这里插入图片描述
    本篇重点:
    (1)进程是进程实体的运行过程,是动态的,是系统进行资源分配和调度的一个独立单位
    (2)PCB是进程存在的唯一标志,判断数据是否在PCB中只需判断数据是否为操作系统对并发过程进行管理的数据,而程序本身运行所需的数据在程序段、数据段中
    (3)进程的组织形式和特征了解即可,但重点是,进程的动态性是进程的基本特征;进程的独立性:进程是系统进行资源分配、调度的独立单位;进程的异步性:各进程以不可预知的速度向前推进,可能导致运行结果的不确定性

    展开全文
  • Linux进程结构及组织方式研究.pdf
  • 进程控制块PCB的组织方式.pptx
  • 1. 知识总览 ...引入多道技术后,内存中可以同时存放多个程序,系统为每个运行的程序配置一个PCB(进程控制块),用来描述进程的各种信息(如程序代码和数据放在哪里) PCB,程序段,数据段 组成一个 进程...

    1. 知识总览

    在这里插入图片描述

    2. 进程的定义

    先来看看什么是程序,程序就是一系列指令序列的集合

    程序运行时,程序代码存放在内存中的程序段中,程序处理的数据(变量)放在数据段中

    为了提高计算机资源的利用率,引入了多道程序技术。

    引入多道技术后,内存中可以同时存放多个程序,系统为每个运行的程序配置一个PCB(进程控制块),用来描述进程的各种信息(如程序代码和数据放在哪里)

    PCB,程序段,数据段 组成一个 进程实体。

    而进程是程序的一次执行过程,是动态的。进程是系统进行资源分配和调度的一个独立单位,是资源分配的最小单位。

    创建进程时新建PCB并分配PID,进程结束后撤销PCB。进程存在的唯一标志是PCB
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    PCB中应含有操作系统对其进行管理所需的各种信息

    3. 进程的组成

    在这里插入图片描述
    操作系统所需的所有信息都在PCB中

    注意,当进程进程切换时,要把cpu寄存器中的状态保持起来,放在PCB中,以便切换回来能正常运行
    在这里插入图片描述
    在这里插入图片描述

    4. 进程的组织方式

    分为链接方式和索引方式

    链接方式:按照进程状态将PCB分为多个队列,操作系统持有指向各个队列的指针

    索引方式:按照进程状态,分别建立索引表。操作系统持有指向各个索引表的指针
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    5. 进程的特征

    进程和程序截然不同!!!

    进程是程序的执行过程!是动态的

    进程具有独立性(资源分配,调度的独立单位),并发性,异步性,结构性(PCB+程序段+代码段)
    在这里插入图片描述
    总结:

    进程是进程实体的运行过程,是资源分配和调度的独立单位

    PCB是进程存在的唯一标志

    PCB中含有操作系统所需的关于进程的全部信息
    在这里插入图片描述

    展开全文
  • 进程控制块PCB(Process Control Block),它是进程实体的一部分,是操作系统中最重要的记录型数据结构。PCB 中记录了操作系统所需的、用于描述进程的当前情况以及控制进程运行的全部信息。进程控制块的作用是使一个在...

       进程控制块PCB(Process Control Block),它是进程实体的一部分,是操作系统中最重要的记录型数据结构。PCB 中记录了操作系统所需的、用于描述进程的当前情况以及控制进程运行的全部信息。进程控制块的作用是使一个在多道程序环境下不能独立运行的程序(含数据),成为一个能独立运行的基本单位,一个能与其它进程并发执行的进程。(系统根据PCB感知进程的存在,即PCB是进程常驻于内存中的唯一标志)

    进程控制块PCB的四种控制信息

    1) 进程标识符

    (1) 内部标识符

    操作系统为每一个进程赋予的唯一数字标识符,系统使用

    (2) 外部标识符

    有创建者提供,通常有字母与数字组成,往往是由用户(进程)在访问该进程时使用。

    描述进程的家族关系,设置父进程标识及子进程标识,还可设置用户标识,以指示拥有该进程的用户。

    2) 处理机状态(处理机状态信息)

    主要是由处理机的各种寄存器中的内容组成的,处理机被中断时,所有这些信息都必须保存在PCB中,

    以便在该进程重新执行时,能从断点继续执行。

    通用寄存器、指令计数器、程序状态字PSW、用户栈指针

    3) 进程调度信息(与进程调度和进程对换有关的信息)

    进程状态

    进程优先级

    进程调度所需的其它信息:与进程调度算法有关事件,指进程由执行状态转变为阻塞状态所等待发生的事件,即阻塞原因

    4) 进程控制信息

    程序和数据的地址

    进程同步和通信机制

    资源清单:除CPU以外的、进程所需的全部资源及已经分配到该进程的资源

    链接指针:了本进程(PCB)所在队列中 的下一个进程的 PCB的首地址

    组织方式

    1)线性表方式:不论进程的状态如何,将所有的PCB连续地存放在内存的系统区。这种方式适用于系统中进程数目不多的情况,不适合频繁的进程调度

    2)索引表方式:该方式是线性表方式的改进,系统按照进程的状态分别建立就绪索引表、阻塞索引表等。其中进程阻塞可能由于I/O请求、申请缓冲区失败、等待解锁、获取数据失败等原因造成,将其组成一张表忽略了进程的优先级,不利于进程的唤醒。

    3)链接表方式:系统按照进程的状态将进程的PCB组成队列,从而形成就绪队列、阻塞队列、运行队列等。

    展开全文
  • Linux进程结构及组织方式研究
  • 进程控制块组织方式

    千次阅读 2017-02-13 20:35:04
    进程控制块PCB的组织方式 1)线性表方式:不论进程的状态如何,将所有的PCB连续地存放在内存的系统区。这种方式适用于系统中进程数目 不多的情况。 2)索引表方式:该方式是线性表方式的改进,系统按照进程的...
  • 操作系统:linux 处理器:arm 内核版本:4.x 目录: 进程状态 组织方式 进程状态 组织方式
  • 3、进程控制块及其作用、组织方式

    万次阅读 2017-11-03 21:37:25
    进程控制块中的信息1) 进程标识符(1) 内部标识符 操作系统为每一个进程赋予的唯一数字标识符,系统使用 (2) 外部标识符 有创建者提供,通常有字母与数字组成,往往是由用户(进程)在访问该进程时使用。描述进程的...
  • 一,定义:在计算机发展史上,进程是为了解决什么问题被引入的呢 回顾:引入多道程序后,为了方便管理程序之间的并发执行,所以我们引入进程的概念 我们知道程序是由程序段和数据段组成的,程序段存的是程序的机器...
  • 进程控制块及其作用、组织方式

    千次阅读 2018-05-30 16:30:03
    进程控制块中的信息1) 进程标识符(1) 内部标识符 操作系统为每一个进程赋予的唯一数字标识符,系统使用 (2) 外部标识符 有创建者提供,通常有字母与数字组成,往往是由用户(进程)在访问该进程时使用。描述进程的...
  • 下图所示的PCB(进程控制块)的组织方式是(),图中()。 A.链接方式 B.索引方式 C.顺序方式 D.Hash A.有1个运行进程、2个就绪进程、4个阻塞进程 B.有2个运行进程、3个就绪进程、2个阻塞进程 C.有1个运行进程、3个...
  • 进程组织

    千次阅读 2017-02-03 16:17:58
    进程是操作系统的资源分配和独立运行的基本单位。它一般由以下三个部分组成。 进程控制块 进程创建时,操作系统就新建一个PCB结构,它之后就常驻内存,任一时刻可以存取, 在进程结束时删除。PCB是进程实体的一...
  • 2进程和线程.xmind

    2022-03-16 13:41:00
    进程【动态的】 概念 进程进程实体的运行过程,是系统进行资源分配和调度的一个独立单位 程序顺序执行 封闭性 程序在封闭的环境下运行,即程序... PCB的组织方式 线性方式 链接方式 索引方式
  • 用户管理计算机就是管理这一堆进程操作系统如何组织多个进程即根据PCB、根据状态形成不同的队列放在不同的位置。多个进程如何组织呢?用PCB放在不同的队列中(就绪、阻塞),用状态转化来推进多个进程的执行操作系统...
  • 进程的定义、组成、组织方式、特征进程的定义进程的组成进程的组织进程的特征总结 进程的定义 进程的组成 进程的组织 进程的特征 总结
  • 在OS中引入进程后,一方面使系统的吞吐量和资源的利用率得到提升,另一方面也使得系统变得复杂,如果没有合理的方式进程进行妥善的管理,必然会引起进程对系统资源的无序竞争,使系统变得混乱;为了实现对并发进程...
  • 进程进程(Process)是计算机中的程序关于某...程序是指令、数据及其组织形式的描述,进程是程序的实体。进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念...
  • Linux进程概念

    千次阅读 多人点赞 2022-03-03 08:54:33
    Linux进程概念零、前言一、冯诺依曼体系结构二、操作系统三、进程1、描述进程-PCB2、查看进程3、获取进程标示符4、创建进程-fork()5、进程状态6、僵尸进程7、孤儿进程8、进程优先级9、环境变量1)测试PATH2)测试HOME3...
  • 进程间通信的方式总结(特点,以及code demo)

    千次阅读 多人点赞 2018-10-08 19:50:39
    进程间通信(IPC,InterProcess Communication):是指在不同进程之间传播或交换信息。 一、简单的进程间通信: 命令行:父进程通过exec函数创建子进程时可以附加一些数据。 环境变量:父进程通过exec函数创建...
  • 进程和线程的定义及区别一, 进程的概念进程是在多道程序系统出现以后,为了描述系统内部各作业的活动规律而引进的概念。由 于多道程序系统所带来的复杂环境,程序本身有了并行性【为了充分利用资源,在主存中同时...
  • 而这个新创建出来的进程被称为原进程的子进程,原进程被称为该进程的父进程。 该函数其实是一个系统调用接口,原型如下: #include <unistd.h> pid_t fork(void); 特性:子进程会复制父进程的PCB,二者之间...
  • Python 多进程进程间通信

    千次阅读 多人点赞 2020-09-03 21:32:33
    作者:billy 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明...进程与程序不同,程序本身只是指令、数据及其组织形式的描述,进程才是程序的真正运行实例。 创建进程的常用方式 在 Pyth
  • Linux如何实现进程的调度

    千次阅读 2021-12-13 19:43:39
    文章目录Linux如何实现进程的调度Linux进程的数据结构创建 task_struct 结构Linux 进程地址空间Linux 进程文件表Linux 进程调度进程调度实体进程运行队列调度实体和运行队列的关系调度器类Linux 的 CFS 调度器普通...
  • 进程组织方式进程的创建; 进程的调度。 3.实验内容 编写程序完成单处理机系统中的进程调度,要求采用时间片轮转调度算法。实验具体包括:首先确定进程控制块的内容,进程控制块的组成方式;然后完成进程创建...
  • 进程的概念与进程控制
  • 操作系统 考研辅导 考研大纲 (一) 进程与线程 1进程概念 2进程的状态与转换 3进程控制 4进程组织 5进程通信共享存储系统消息传递系统管道通信 6线程概念与多线程模型 (二) 处理机调度 1调度的基本概念 2调度时机切换...
  • 操作系统之进程 (五) --- 进程进程实体、PCB...

    千次阅读 多人点赞 2019-08-03 08:17:15
    进程 什么叫进程 进程和程序差不多,只不过有些细微的区别。 我们以我们熟悉的程序入手,看看什么是进程进程有一个定义:进程是程序的一次执行过程。 什么意思呢?我们以编写程序到运行程序的整个过程看看。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 181,775
精华内容 72,710
关键字:

进程组织方式