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

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  等信号的时候,此外,在调试期间接收到的任何信号,都会是进程进入这种状态。
  状态之间的切换关系如图:
  本文只介绍了进程的内核基础知识,后续通过源码进一步分析相关进程管理的知识。

2023,致自己图片来源网络时光跌跌撞撞生活磕磕绊绊,转眼我们又进入新的一年。如今,站在时光的渡口往回看,不知不觉,我们已走了很远的路。杨绛先生曾说人生一站有一站的风景,一岁有一岁的味道。生活没有北汽蓝谷2022年预亏52亿元至58亿元中证网讯(记者金一丹)1月30日晚,北汽蓝谷发布2022年年度业绩预告称,报告期内,公司预计亏损52亿至58亿元。北汽蓝谷表示,一方面,2022年上游原材料价格上涨带来动力电池等零村界杯火了,体育本就该是这样在这个春节,江苏徐州沛县的村界杯火了。从初一到初七,每天都有足球赛在鹿楼镇八堡村举办。虽然气温降至零下,但场上球员们跑得火热,场外村民们热情不减,十里八村的乡亲们自带小马扎前来观赛环球漫评五个一百绘就奋进中国实景图漫画作者殷雯静近日,由中央网信办主办的2022中国正能量五个一百网络精品征集评选展播活动进入作品报送阶段。笔头担道义眼里有风骨文字带观点的精品佳作不断涌现,如盏盏灯火,点亮网络晴空影响明清国运的改革,为何一条鞭法与摊丁入亩的结局不同阅读此文前,麻烦您点击一下关注,既方便您进行讨论与分享,又给您带来不一样的参与感,感谢您的支持。引言在今天,中国是世界上数一数二的农业大国,二十一世纪的中国仍然把粮食问题放在首位,证监会宣布!2月6日正式启动,首批名单来了!2月3日,证监会表示,交易所债券市场正式启动债券做市业务。为推进债券市场高质量发展,提升市场活力,完善价格发现机制,近年来,证监会持续指导沪深交易所加强二级市场建设有关工作。目前,重镑以工代赈实施有人喊高启盛李村长不要再打了,来大活了为避免被造谣,我专门搜索了国家以工代赈管理办法。确认这话无误。还可以不进行招标劳动者个体直接参与。这可是天大的好事呀!首先说明这可是大肥肉,能者吃得满脑肥肠!因为这个政策的实施,估浓眉3114,詹姆斯2677,湖人队112111末节逆转险胜步行者!北京时间2月3日上午800NBA常规赛湖人队客场挑战步行者队,其首发阵容为施罗德贝弗利八村塁詹姆斯浓眉戴维斯步行者队首发为哈利伯顿内姆哈德希尔德内史密斯特纳。双方第一节开打,希尔德开云体育与莱斯特城官宣达成合作中新网上海新闻2月3日电(记者缪璐)经过长期沟通谈判,开云体育与英超劲旅莱斯特城通过线上线下的方式正式签署协议,成为俱乐部官方区域合作伙伴。未来一段时间里双方秉着合作共赢互惠互利的NBA直播中雄鹿vs快船直播中比赛时间2023年2月3日,密尔沃基雄鹿vs洛杉矶快船比赛性质2023年NBA直播观赛入口httpzb。laiqw。cnm?fromanlan3(长按链接后点击搜索即可直达)这事让好消息2024年巴黎奥运会中国金牌榜将排第一日前,波兰体育和旅游部长卡米尔说,他们准备组成一个由英国,美国,加拿大,波兰立陶宛爱沙尼亚和拉脱维亚等40个国家的联盟来共同抵制2024年巴黎奥运会,以反对国际奥委会(IOC)允许
活色生香的荷兰阿姆斯特丹橱窗女郎赌场大麻合法的艺术之都这是一座非常奇特的城市地势低于海平面15米,有160多条大小水道,由1000余座桥梁相连,被称为北方威尼斯。它同时也是一个非常自由开放的城市,这里有著名的红灯区橱窗女郎一条街,有合三大消息1月26日,德媒嘲讽军演意副外长透实情美强硬表态在中美博弈的背景下,美国正意图让台湾问题国际化,而迫使中国不得不接受一个美国主导下的台海局势。而为了反制以美国为代表的域外势力的干预,我们更是通过强有力的军事手段对美国及岛内民进党津市交警携手小志愿者开展交通安全宣传活动红网时刻常德1月26日讯(通讯员宋丹阳)进一步提高交通参与者的安全意识和文明出行意识,努力营造安全畅通和谐有序的道路交通环境。1月25日,春节第四天,津市公安局交警大队携手小志愿者再婚有新欢找帅哥老牛吃嫩草开年7个恋情瓜,太乱了沉寂了几年的电影行业,终于是慢慢复苏了。2023年的春节档,彻底火热了起来,截止大年初四晚10点2023春节档票房破50亿。一切好像都在慢慢变好。娱乐圈更是跟着春节档,慢慢热闹了起江苏淮安清江浦区四送活动推动双拥工作开门红在喜迎新春之际,江苏省淮安市清江浦区军地联合开展送立功喜报活动,敲锣打鼓,把尊崇送到军人家中。在三等功臣刘雅昆家中,他与前来的军地群众学生志愿者们分享了在军营的训练生活点滴和个人感新春走基层天梯之下的戍边年新春走基层原标题天梯之下的戍边年工人日报客户端记者赵黎浩通讯员马玲视频加载中在云南省红河州河口县桥头乡,81公里的边境线绵延穿梭于层层浓雾之间,这里有云雾缭绕的山林,星罗棋布的村庄江苏南通姑娘远嫁美国,生2娃,文化差异大中国妈妈飞去照顾月子她叫小黄,1992年出生于,中国江苏南通的一个小镇上。大学毕业之后,她在上海的一家中文学校当顾问。主要的业务是,给来中国上学工作的外国人,销售课程。基于工作的便利,她认识了来自美国上映两天,紧急撤档!被打回原形的邓超,午夜梦回可曾后悔?名声狼藉的好莱坞影帝凯文史派西,对自己演员身份的认知,却格外清醒。对自己的生活,我一直只字不提,这不是为了故作神秘。而是你了解一个演员本人越少,越有利于让你相信,他就是荧幕上的那个为什么人人都觉得现在的年味儿淡了?不外乎这些原因今天已经大年初五了,按照传统习俗过了初五基本这个年也就算过完了,现在真的是感觉年味儿越来越淡了,过年也越来越没意思!那么,究竟是什么原因致使现在的年味儿越来越淡了呢?仔细想来也不在北约同意提供坦克说明什么在这之前很多人说北约不会提供坦克,我也明白他们这样判断是基于觉得北约怕俄罗斯急了,会用核武器或者直接打击北约国家。从而让战争升级,从和北约关系不大的局部战争,变成直接和北约开战的全培育文明乡风良好家风淳朴民风图依山傍水的浙江温州市瓯海区源口村龙溪艺术馆。周方摄图孩子们在河南孟州市莫沟村老苗书馆度过难忘的阅读时光。张泽斌摄图在广东中山市左步村,农家书屋的玻璃书房在稻田边古树旁,别具一格。