设为首页 收藏本站
查看: 594|回复: 0

[经验分享] linux进程和task_struct()简介

[复制链接]

尚未签到

发表于 2017-11-17 15:32:58 | 显示全部楼层 |阅读模式
  一、构成进程的要素
  在linux系统中,进程主要具备以下要素:
  1)有一个程序供其运行。这段程序不一定是进程所专有,可以与其他进程一起使用;
  2)有起码的“私有财产”,这就是进程专用的系统堆栈空间;
  3)有“身份证”,也就是task_struct结构,也称之为“进程控制块”(PCB)。有了这个数据结构,进程才能成为内核调度的一个基本单位接受内核的调度。同时,这个结构又是进程的“财产登记卡”,记录着进程占用的各项资源。
  4)有独立的存储空间,意味着拥有专有的用户空间;还意味着除前述的系统空间堆栈外还有其专有的用户空间堆栈。(PS:进程的系统空间是不能独立的,除了各进程独有的系统堆栈空间外,任何进程都不可能直接改变用户空间的内容)。
  以上条件是必要条件,缺少其中一条,都不能称其为“进程”。如果只缺第四条,那就成为“线程”。特别地,如果完全没有用户空间,就称其为“内核线程”;而如果共享用户空间则称其为“用户线程”。在不致引起混淆的场合,二者也往往简称为“线程”。注意!!!这里的线程与有些操作系统中在用户空间的同一进程内实现的“线程”不一样!既然linux提供了对上述内核线程和用户线程的支持,也就没必要再在进程内部,即用户空间内自行实现线程。
  关于进程和线程的区分不是十分严格,在linux系统中,许多进程在诞生之初都与其父进程共同用一个存储空间,所以也就是用户线程。但是子进程又可以建立自己的存储空间,并与父进程“分道扬镳”,成为与父进程一样真正意义上的进程。
  在linux系统中,“进程”和“任务”是同一个意思,在内核的代码中常混用这两个名词和概念。例如每个进程都要有一个task_struct数据结构,而其号码却又是pid、唤醒一个睡眠进程的函数名为wake_up_process(),之所以有这样的情况是因为,linux源自Unix和i386系统结构,而unix中的进程在Intel的技术资料中称为“任务”,严格来说有点区别,但是对于系统的实现来说是一回事。
  linux系统运行的第一个进程是在初始化阶段“捏造出来的”。而此后的线程或进程都是由一个已存在的进程像细胞分裂一样通过系统调用复制出来的,成为“fork()”或者“clone()”。
  除了最起码的“财产”,即task_struct数据结构和系统堆栈之外,一个进程还要有一些附加的资源。例如,进程拥有堵路的存储空间,就要有用于虚拟内存管理的mm_struct数据结构以及附属的vm_area数据结构,以及相应的页面目录项和页面表,但这些都从属于task_struct资源。task_struct数据结构在这方面相当于登记卡的作用。
  二、task_struct的定义
  task_struct结构源代码:



struct task_struct
{
     /*
      * offsets of these are hardcoded elsewhere - touch with care
      */
     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 */
     /*
      * offset 32 begins here on 32-bit platforms. We keep
      * all fields in a single cacheline that are needed for
      * the goodness() loop in schedule().
      */
     long counter;
     long nice;
     unsigned long policy;
     struct mm_struct *mm;
     int has_cpu, processor;
     unsigned long cpus_allowed;
     
     struct list_head run_list;
     unsigned long sleep_time;
     
     struct task_struct *next_task, *prev_task;
     struct mm_struct *active_mm;
     /* task state */
     struct linux_binfmt *binfmt;
     int exit_code, exit_signal;
     int pdeath_signal;  /*  The signal sent when the parent dies  */
     unsigned long personality;
     int dumpable:1;
     int did_exec:1;
     pid_t pid;
     pid_t pgrp;
     pid_t tty_old_pgrp;
     pid_t session;
     pid_t tgid;
     /* 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)
      */
     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;
     wait_queue_head_t wait_chldexit; /* for wait4() */
     struct semaphore *vfork_sem; /* for vfork() */
     unsigned long rt_priority;
     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;
     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 */
     unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
     int swappable:1;
     /* process credentials */
     uid_t uid,euid,suid,fsuid;
     gid_t gid,egid,sgid,fsgid;
     int ngroups;
     gid_t groups[NGROUPS];
     kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
     int keep_capabilities:1;
     struct user_struct *user;
     /* limits */
     struct rlimit rlim[RLIM_NLIMITS];
     unsigned short used_math;
     char comm[16];
     /* file system info */
     int link_count;
     struct tty_struct *tty; /* NULL if no tty */
     unsigned int locks; /* How many file locks are being held */
     /* ipc stuff */
     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;
     struct sigpending pending;
     
     unsigned long sas_ss_sp;
     size_t sas_ss_size;
     int (*notifier)(void *priv);
     void *notifier_data;
     sigset_t *notifier_mask;
     
     /* Thread group tracking */
     u32 parent_exec_id;
     u32 self_exec_id;
     /* Protection of (de-)allocation: mm, files, fs, tty */
     spinlock_t alloc_lock;
};
  下面对结构中几个重要的成分做介绍:
  1)state(第6行)
  该变量表示进程当前运行的状态,具体定义如下:



#define TASK_RUNNING              0
#define TASK_INTERRUPTIBLE        1
#define TASK_UNINTERRUPTIBLE      2
#define TASK_ZOMBIE               4  //僵尸进程
#define TASK_STOPPED              8
  状态TASK_INTERRUPTIBLE和TASK_UNINTERRUPTIBLE均表示进程处于睡眠状态。但是TASK_UNINTERRUPTIBLE表示进程处于“深度睡眠”,而不受“信号”(signal,也称软中断)的打扰,而TASK_INTERRUPTIBLE则可以因信号的到来而被唤醒。内核中提供了不同的函数,让一个进程进入不同深度的睡眠或将进程从睡眠中唤醒。具体地说,函数sleep_on()和wake_up()用于深度睡眠,而interruptible_sleep_on()和wake_up_interruptible()则用于浅度睡眠。深度睡眠一般只用于临界区和关键性的部位,而“可中断”的睡眠那就是通用的了。特别地,当进程在“阻塞性”的系统调用中等待某一事件发生时,应该进入可中断睡眠,否则就不能对别的中断做出反应,别的进程就不能通过发一个信号来“杀掉”这个进程了。
  TASK_RUNNING状态并不是表示一个进程正在执行中,或者说这个进程就是“当前进程”,而是表示这个进程可以被调度执行而成为当前进程。当进程处于这样的可执行(或就绪)状态时,内核就将该进程的task_struct结构通过其队列头(见第30行)挂入一个“运行队列”。
  TASK_ZOMBIE状态表示进程已经“去世”而户口尚未注销。
  TASK_STOPPED主要用于调试的目的,进程接收到 一个SIGSTOP信号后就将运行状态改成     TASK_STOPPED而进入“挂起”状态,然后在接收到SIGCONT信号时又恢复继续运行。
  2)flags(第7行)
  flags反应进程状态相关信息,但并不是运行状态,而是与管理有关的其他信息。



#define PF_ALIGNWARN        0x00000001      /*print alignment warning msgs*/
#define PF_STARTING         0x00000002      /*being created*/
#define PF_EXITING          0x00000004      /*getting shut down*/
#define PF_FORKNOEXEC       0x00000040      /*forked but did not exec*/
#define PF_SUPERPRIV        0x00000100      /*uses super-user privileges*/
#define PF_DUMPCORE         0x00000200      /*dumped core*/
#define PF_SIGNALED         0x00000400      /*killed by signal*/
#define PF_MEMALLOC         0x00000800      /*Allocating memory*/
#define PF_VFORK            0x00001000      /*wake up parent in mm_release*/
#define PF_USEDFPU          0x00100000      /*task used FPU this quantum(SMP)*/
  3)sigpending(第8行)
  表示进程收到了“信号”但是尚未处理。
  4)counter(第23行)
  与进程调度有关
  5)add_limit
  虚拟地址空间的上限,对进程而言是其用户空间的上限,所以是0xbfff ffff;对内核线程而言则是系统空间额的上限,所以是0xffff ffff
  6)binfnt
  应用程序的文件格式。
  7)pgrp,session,leader
  当一个用户登录时,就开始了一个进程组(session),此后创建的进程都属于这同一个session。
  8)user
  指向一个user_struct结构,该数据结构代表进程所属的用户。
  9)rlim
  这是一个结构数组,表明进程岁各种资源的使用数量所受的限制。
  参考:
  毛德操,胡希明《linux内核源代码情景分析》(上册)

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-407932-1-1.html 上篇帖子: ScriptEngineManager linux 失效 下篇帖子: Linux--VSFTP服务搭建
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表