范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Linux进程管理之基础知识

  task_struct 结构描述
  在 Linux 中每个进程都是由一个 task_struct  结构来进行描述的。通常我们常说的 PBC (进程控制块)就是指 task_struct 。
  task-struct  结构包含了进程的所有信息,它是系统对进程进行控制的有效手段。
  task_struct  结构进行具体描述如下
  struct task_struct {      /*       进程执行时,它会根据具体情况改变状态,Linux 中的进程主要有如下状态       TASK_RUNNING  可运行       TASK_INTERRUPTIBLE  可中断的等待状态       TASK_UNINTERRUPTIBLE 不可中断的等待状态       TASK_ZOMBIE 僵死       TASK_STOPPED  暂停      */      volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */     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                      */     struct exec_domain *exec_domain;     volatile long need_resched;     unsigned long ptrace;     //上下文切换时内核锁的深度     int lock_depth;     /* Lock depth */      long counter; //进程剩余的时间片     long nice;     /*进程调度策略,有3种        SCHED_OTHER 其他调度, 普通进程调度策略       SCHED_FIFO  先来先服务调度  实时进程调度策略       SCHED_RR  时间片轮转调度   实时进程调度策略     */      unsigned long policy;     //描述进程的地址空间     struct mm_struct *mm;     int processor; //进程当前正在使用的CPU      struct list_head run_list; //运行队列的链表     unsigned long sleep_time;     //进程在双向循环链表中的链接     struct task_struct *next_task, *prev_task;     /*      active_mm,这是为内核线程而引入的。因为内核线程没有自己的地址空间,为了让内核线程与普通进程具有统一的上下文      切换方式,当内核线程进行上下文切换时,让切换进来的线程的active_mm 指向刚被调度出去的进程的      active_mm(如果进程的mm 域不为空,则其active_mm 域与mm 域相同)。     */     struct mm_struct *active_mm; //内核线程所借用的地址空间     struct list_head local_pages;     unsigned int allocation_order, nr_local_pages;  /* task state */     //指向进程所属的全局执行文件格式结构,共有a.out、script、elf、java 等4 种     struct linux_binfmt *binfmt;     //程序的返回代码以及程序异常终止产生的信号,这些数据由父进程(子进程完成后)轮流查询     int exit_code, exit_signal;     int pdeath_signal;  /*  The signal sent when the parent dies  */     /* ??? */     unsigned long personality;     //按POSIX 要求设计的布尔量,区分进程正在执行老程序代码,还是用系统调用execve()装入一个新的程序     int did_exec:1;      pid_t pid; //进程标识符      /* 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)      */     /*       p_opptr Original parent 祖先       p_pptr Parent 父进程       p_cptr Child 子进程       p_ysptr Younger sibling 弟进程       p_osptr Older sibling 兄进程     */      struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;     struct list_head thread_group;      /* PID hash table linkage. */     //进程在哈希表中的链接     struct task_struct *pidhash_next;     struct task_struct **pidhash_pprev;     /*在进程结束时,或发出系统调用wait4 时,为了等待子进程的结束,而将自己(父进程)       睡眠在该等待队列上,设置状态标志为TASK_INTERRUPTIBLE,并且把控制权转给调度程序*/     wait_queue_head_t wait_chldexit;    /* for wait4() */     struct completion *vfork_done;      /* for vfork() */     unsigned long rt_priority; //实时优先级     /*进程有3 种类型的定时器:     实时定时器: 实时更新,即不论该进程是否运行 it_real_value、it_real_incr、real_timer     虚拟定时器: 只在进程运行于用户态时更新 it_virt_value、it_virt_incr     概况定时器: 进程运行于用户态和系统态时更新 it_prof_value、it_prof_incr     */     unsigned long it_real_value, it_prof_value, it_virt_value;     unsigned long it_real_incr, it_prof_incr, it_virt_incr;     struct timer_list real_timer;     struct tms times;     unsigned long start_time; //进程创建时间     /*         per_cpu_utime 进程在某个CPU 上运行时在用户态下耗费的时间         per_cpu_stime 进程在某个CPU 上运行时在系统态下耗费的时间     */     long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS]; /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */      /*      min_flat,maj_flt,nswap 进程累计的次(minor)缺页次数、主(major)次数及累计换出、换入页面数      cmin_flat,cmaj_flt,cnswap 本进程作为祖先进程,其所有层次子进程的累计的次(minor)缺页次数、主(major)次数及累计换出、换入页面数        */     unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;     int swappable:1; //进程占用的内存页面是否可换出 /* process credentials */     /*         Uid、gid  用户标识符、组标识符         Euid、egid 有效用户标识符、有效组标识符         Suid、sgid  备份用户标识符、备份组标识符         Fsuid、fsgid 文件系统用户标识符、文件系统组标识符       */     uid_t uid,euid,suid,fsuid;     gid_t gid,egid,sgid,fsgid;     ... /* limits */     //每一个进程可以通过系统调用setlimit 和getlimit 来限制它资源的使用     struct rlimit rlim[RLIM_NLIMITS];     unsigned short used_math;     //这个域存储进程执行的程序的名字,这个名字用在调试中     char comm[16];      struct sem_undo *semundo; //为避免死锁而在信号量上设置的取消操作     struct sem_queue *semsleeping; //与信号量操作相关的等待队列 /* CPU-specific state of this task */     struct thread_struct thread; /* filesystem information */     struct fs_struct *fs; //进程的可执行映像所在的文件系统 /* open file information */     struct files_struct *files; //进程打开的文件 /* signal handlers */     //信号掩码的自旋锁     spinlock_t sigmask_lock;    /* Protects signal and blocked */     struct signal_struct *sig; //信号处理函数      sigset_t blocked; //信号掩码     ... };
  进程就是处于执行期的程序,但进程不仅仅局限于一段可执行程序代码(也就是所谓的代码段, text section ),从上面的数据结构可以看到,进程还包含其他的资源,比如打开的文件,挂起的信号,处理器状态,内核数据结构,内存映射地址空间等。
  在操作系统中,内核的调度对象时线程,而不是进程。线程时进程中的活动对象。每个线程都拥有一个独立的程序计数器、进程栈和一组进程程寄存器。
  在传统的 Unix 系统中,一个进程只包含一个线程,但是在现代操作系统中,一个进程可以包含多个线程。在 Linux 系统中线程的实现非常特别:它对线程和进程并不特别区分。对于 Linux 而言,线程只不过是一种特殊的进程罢了。后续的文章专门介绍进程和线程的创建过程进行分析。
  在操作系统中,内核把进程的列表存放在一个叫任务队列的双向循环链表中,链表中的每个元素类型就是上述的数据结构  task_struct , 称为进程描述符的结构。该结构中包含了具体进程的所有信息。task_struct  在32位机器上,大约有1.7KB的大小。
  task_struct 结构在内存中的存放
  在分析之前,需要了解下一个概念 -- 内核栈。
  我们知道一个在32系统中,进程的虚拟地址空间大小为4G。在这4G虚拟机制空间中有一段虚拟地址空间为栈的区域,该栈的区域为用户态栈。该栈记录的是在用户态进程的函数调用过程。
  但是当进程进行系统调用时进入内核态时,在内核中使用的栈不再是上述的用户态的栈了,而是单独的内核空间的栈,称为内核栈。每个进程都有各自的内核栈。该栈是在进程创建时生成的。
  当进程从用户态进入内核态时,CPU 就自动地设置该进程的内核栈,也就是说,CPU 从任务状态段 TSS 中装入内核栈指针 esp。
  在 Intel 系统中,栈起始于末端,并朝这个内存区开始的方向增长。从用户态刚切换到内核态以后,进程的内核栈总是空的,后续有数据开始写入栈中时,esp 的值就递减。
  内核栈在不同的版本中表示的也不大相同,在2.4版本中内核栈空间和  task_struct  结构时存放到一块的。//2.4内核栈表示方式  union task_union { struct task_struct task; unsigned long stack[INIT_TASK_SIZE/sizeof(long)]; };
  从这个结构可以看出,内核栈占8KB 的内存区。实际上,进程的 task_struct  结构所占的内存是由内核动态分配的,更确切地说,内核根本不给 task_struct  分配内存,而仅仅给内核栈分配8KB 的内存,并把其中的一部分给 task_struct  使用。
  task_struct  结构大约占1K 字节左右,其具体数字与内核版本有关,因为不同的版本其域稍有不同。因此,内核栈的大小不能超过7KB,否则,内核栈会覆盖 task_struct  结构,从而导致内核崩溃。不过,7KB 大小对内核栈已足够。
  把  task_struct  结构与内核栈放在一起具有以下好处:内核可以方便而快速地找到这个结构,用伪代码描述如下: task_struct  = (struct task_struct *) STACK_POINTER & 0xffffe000 避免在创建进程时动态分配额外的内存。 task_struct  结构的起始地址总是开始于页大小(PAGE_SIZE )的边界。
  内核栈的分布图如下:
  获取当前进程指针时,操作如下: static inline struct task_struct * get_current(void) { struct task_struct *current; __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL)); return current; }  #define current get_current()
  实际上,这段代码相当于如下一组汇编指令(设p 是指向当前进程 task_struc  结构的指针):movl $0xffffe000, %ecx  andl %esp, %ecx  movl %ecx, p
  换句话说,仅仅只需检查栈指针的值,而根本无需存取内存,内核就可以导出
  task_struct  结构的地址。
  在2.6以前,各个进程的  task_struct  存放在他们内核栈的尾端。这样做的目的是为了让那些像X86那样寄存器较少的硬件体系结构只要通过栈指针就能计算出它的位置,而避免使用额外的寄存器专门记录。
  而在2.6中使用的  slab  分配器动态的生成 task_struct  结构,所以只需在栈底(对于向下增长的栈而言)或栈顶(对于向上增长的栈而言)创建一个新的数据结构 thread_info 。这个新建的数据结构在汇编代码中计算器偏移量变得非常容易。
  其结构如下: //2.6 内核栈表示方式  union thread_union { struct thread_info thread_info; unsigned long stack[THREAD_SIZE/sizeof(long)]; }; thread_info 结构如下: struct thread_info { struct task_struct *task; /* main task structure */ __u32 cpu; /* current CPU */  ...  };
  在2.6中的  task_struct   中,存在一个stack  字段指向 thread_info struct task_struct { volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ void *stack; // 指向 thread_info 的指针 ... }
  内核栈的分布图如下:
  当获取当前进程信息时,可通过 current_thread_info() 获取。   #define get_current() (current_thread_info()->task) #define current get_current()
  在X86系统上, current  都是把栈指针的后13个有效位屏蔽掉,用来计算偏移进行获取 的。,汇编代码如下:movl $-8192, %eax  andl %esp, %eax
  最后,current 再从  thread_info  的 task 域中提取并返回  task_struct  的地址
  current_thread_info()->task
  进程状态
  在  task_struct  中  state  描述了进程的当前状态。系统中的每个进程一定处于如下5中状态中的一种,因此  state  也必为如下5种状态标志之一。 TASK_RUNNING (可运行): 进程是可执行的,或者正在执行,或者在运行队列中等待执行。 正在运行的进程就是当前进程(由 current  所指向的进程),而准备运行的进程只要得到CPU 就可以立即投入运行,CPU 是这些进程唯一等待的系统资源。系统中有一个运行队列,用来容纳所有处于可运行状态的进程,调度程序执行时,从中选择一个进程投入运行TASK_INTERRUPTIBLE (可中断): 进程正在睡眠(阻塞),在等待某些条件的达成,一旦这些条件达成,内核就把进程状态设置为可运行。处于此状态的进程也会因为接收到信号而提前被唤醒并随时准备投入运行。 TASK_UNINTERRUPTIBLE (不可中断):除了就算是接收到信号也不会被唤醒或者准备投入运行外,这个状态与可打断状态相同。该状态通常在进程必须在等待时不受干扰或者等待事件很快就会发生时出现。由于处于此状态的任务对信号不做响应,所以较之可中断状态,使用的较少。 TASK_ZOMBIE (僵死): 进程虽然已经终止,但由于某种原因,父进程还没有执行wait()系统调用,终止进程的信息也还没有回收。顾名思义,处于该状态的进程就是死进程,这种进程实际上是系统中的垃圾,必须进行相应处理以释放其占用的资源。TASK_STOPPED (暂停):进程停止执行,进程没有投入运行也不能投入运行。通常这种状态发生在接收到  SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOU  等信号的时候,此外,在调试期间接收到的任何信号,都会是进程进入这种状态。
  状态之间的切换关系如图:
  本文只介绍了进程的内核基础知识,后续通过源码进一步分析相关进程管理的知识。

曝陈乔恩烟瘾严重!住酒店满房烟味地上丢满烟头,8年烟瘾难戒断饿了吗?戳右边关注我们,每天给您送上最新出炉的娱乐硬核大餐!11月12日,娱记懂瓜呱直播时和台湾知名记者葛斯齐连线,期间葛斯齐爆料陈乔恩烟瘾严重,住酒店时甚至因为满是烟头遭到了打扫800块钱拍的片,看完直接爽了花了一个小时,品味一部电影。是我阅片生涯浓墨重彩的一笔徒手掰飞机屁股蛋呲血直升机扫射这特效设计,这镜头语言,这剪辑节奏,我就是一整个愣住。先别急着笑。你知道他们有多努力吗?!!绝对京圈太子妃白百何,沉寂5年,带娃复出,她的反击悄无声息2017年,当红女星白百何被娱乐圈纪委卓伟爆料婚内出轨,消息一出,瞬间引爆全网。随着出轨新闻不断发酵,陈羽凡火速发表声明称两人早在2015年已协议离婚,白百何也站出来公开致歉,可是小鹏汇天获60亿元银行授信,致力飞行汽车研发和生产制造新京报贝壳财经讯(记者白昊天)11月9日,贝壳财经记者自小鹏汽车方面了解到,小鹏汇天已与中国农业银行广东省分行中国建设银行广东省分行中信银行广州分行以及浦东发展银行广州市分行正式达报告称越来越多中国女性积极投入科学研究本报讯(中青报中青网记者王烨捷)日前,在第五届世界顶尖科学家论坛她论坛上,中国科学院文献情报中心与爱思唯尔共建的科研评价实验室,联合发布我国第一份以性别视角解读中国科研生态的研究报线下京东11。11人气火爆京东电器线下大店成交额同比增长140以给生活多点实在为主题的京东11。11,在极致性价比海量品质好物以及多重贴心服务保障下,充分激发了消费活力。其中,京东电器线下门店在京东11。11期间,依托线上线下融合的全渠道业态独立站SEO终极小白教学什么是独立站SEO首先独立站SEO(SearchEngineOptimisation)全称搜索引擎优化,是一种通过优化站内站外网站提升自然流量的质与量,这种方法的好处是不用通过广告艰难求生,快递企业鏖战东南亚钛媒体焦点图片来源视觉中国东南亚地区的快递战事再次升级。近期,疑似顺丰针对东南亚出口业务的战狼计划流出,让人们的目光再次投向了东南亚。随着TikTok阿里巴巴等头部互联网电商的布局,中国快递中兴V70Pro新机通过认证,颜值很刚,有7。6mm纤薄身材七彩呼吸灯ZTE中兴通讯今年的战略似乎有较大的调整,旗下努比亚红魔的营销越来越低调,嫡系产品定位则更加实体渠道化,包括远航系列在内的近几款新机都愈发高端起来,中兴旗下若大的手机阵营里,很难让开放合作添活力!长三角国际朋友圈不断壮大,科技创新成果丰硕现代快报讯(记者阿里亚)江苏作为开放大省,在持续提升自主创新能力的同时,积极推进国际科技交流合作。为期三天的中国江苏第八届国际产学研合作论坛暨跨国技术转移大会正在南京举办,来自505亿元资产蒸发!亚马逊退货触目惊心!中国卖家到底怎么办?亚马逊的卖家经常会遇到退货换标的情况,货物无法上架出售会直接影响卖家的收益,接下来还要面临仓储费销毁费等费用,那如何把损失降到最小?下面美新君为卖家讲解FBA退货换标那些事!1。什
队报各方让内马尔暂别国家队疗伤,或在重要大赛前再回归根据法国媒体队报特约记者EricFrosio在里约热内卢发回的报道,对于内马尔来说,右脚踝肿胀,韧带受损,士气低落,这是他在本届世界杯受伤之后的状态。在巴黎派出的理疗师和巴西足协的丁俊晖公开回应假球事件这与学院无关,也与我无关!近日,对于沸沸扬扬的梁文博假球事件,丁俊晖在采访中正式公开回应,这也让球迷们放下担忧和悬着的心,因为,丁俊晖并不知道,也未参与,而且丁俊晖也明确表示目前,他也不想参与其中。丁俊晖近谁说阳了只能喝稀饭?这些食物帮你迅速转阴!随着国家疫情防控政策,疫情管控越来越松,很多城市短时间内出现了大量的阳性感染者。如果不幸感染了,作为小阳人,我们应该做些什么呢?很多阳性感染者通过网络发布感染病毒之后什么都吃不下每安徽294斤孕妇临产,医生吓得不敢开刀,连跑几家医院都被拒绝在阅读此文之前,麻烦您点击一下关注,既方便您进行讨论与分享,又给您带来不一样的参与感,感谢您的支持安徽合肥一位重量级孕妇即将分娩,跑遍了各大医院却被拒之门外,这到底是什么情况?这位孩子阳了怎么办?协和医院李医生问诊主要内容奉上协和医院李医生问诊主要内容,奉上!希望给大家关于新冠治疗有一定的帮助戴口罩戴口罩戴口罩重点注意接下来我说的经验来源于我家孩子高热惊厥后住院的经验总结,也是当时医生教给我的方法!六个夫妻性福生活中,面对体虚情况该怎么办呢?医生坦言科学对待面对夫妻生活,开始有点力不从心,往往都是心有余而力不足对于中年人群来说随着年纪增长,身体开始开始走下坡路,总是觉得自身阳气渐虚没到春秋换季节的时候,和别人穿着差别特别大,别人开始穿湖人2换1报价205锋线!詹姆斯将迎来最佳帮手,湖人起飞了?湖人目前的形势湖人说强也强,说弱也弱,詹姆斯和戴维斯只要爆发,就能和强队扳手腕,最近都是和76人凯尔特人打到加时才败下阵来,但是他们也能和活塞这样的弱队打到最后一分钟才赢球。湖人强200万买下190平豪宅,时隔12年,杜锋赚到了多少钱?数字惊人杜锋,中国男篮历史上最好的球员之一,当年的排骨飞人凭借着炸裂的打法,精准的中远投帮助广东男篮立下赫赫战功。对于自己在走投无路的时候,递出唯一橄榄枝的广东男篮,杜锋有着太多的感情,也快船16分逆转!乔治171111,伦纳德找回自我,泰伦卢终究没白等前言虽说在本赛季之初,快船成为了联盟所有队伍当中,受伤病影响最大的队伍。但是,他们依旧能在主教练泰伦卢的帮助下,不断克服各种困难,持续稳定住球队中等偏上的战绩,等待着卡乔组合的回归如果梅西捧杯的话,就是历史第一球王阿根廷两代GOAT(历史最佳),马拉多纳VS梅西世界杯数据对比出战场次21VS24胜场12VS15平场4VS4负场5VS5进球数8VS10助攻数8VS7场均进球数0。4VS0。4场伯明翰VS雷丁伯明翰近几年一直是典型的英冠下游球队。本赛季至今,伯明翰暂列积分榜第十四,与前两个赛季相比,有所进步。目前22轮取得7胜8平7负积29分。上一场比赛,上轮客场00逼平对手,球队已经