进程数据结构(中)

运行统计信息

在进程运行的过程中,会有一些统计量,具体见下面的表,这里面有进程在用户态和内核态消耗的时间,上下文切换的次数等等。

u64        utime;//用户态消耗的CPU时间
u64        stime;//内核态消耗的CPU时间
unsigned long      nvcsw;//自愿(voluntary)上下文切换计数
unsigned long      nivcsw;//非自愿(involuntary)上下文切换计数
u64        start_time;//进程启动时间,不包含睡眠时间
u64        real_start_time;//进程启动时间,包含睡眠时间

进程亲缘关系


struct task_struct __rcu *real_parent; /* real parent process */
struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports */
struct list_head children;      /* list of my children */
struct list_head sibling;       /* linkage in my parent's children list */

parent 指向其父进程。当它终止时,必须向它的父进程发送信号。children 表示链表的头部。链表中的所有元素都是它的子进程。sibling 用于把当前进程插入到兄弟链表中。如果在 bash 上使用 GDB 来 debug 一个进程,这个时候 GDB 是 parent(SIGCHLD的回收者),bash 是这个进程的 real_parent(真正的父进程)。

进程权限

在Linux中对于进程权限的定义如下:

/* Objective and real subjective task credentials (COW): */
const struct cred __rcu         *real_cred;
/* Effective (overridable) subjective task credentials (COW): */
const struct cred __rcu         *cred;

其中,real_cred 就是说明谁能操作我这个进程,而 cred 就是说明我这个进程能够操作谁。
cred的定义如下:

struct cred {
......
        kuid_t          uid;            /* real UID of the task */
        kgid_t          gid;            /* real GID of the task */
        kuid_t          suid;           /* saved UID of the task */
        kgid_t          sgid;           /* saved GID of the task */
        kuid_t          euid;           /* effective UID of the task */
        kgid_t          egid;           /* effective GID of the task */
        kuid_t          fsuid;          /* UID for VFS ops */
        kgid_t          fsgid;          /* GID for VFS ops */
......
        kernel_cap_t    cap_inheritable; /* caps our children can inherit */
        kernel_cap_t    cap_permitted;  /* caps we're permitted */
        kernel_cap_t    cap_effective;  /* caps we can actually use */
        kernel_cap_t    cap_bset;       /* capability bounding set */
        kernel_cap_t    cap_ambient;    /* Ambient capability set */
......
} __randomize_layout;

一看这个名字,就知道这个是起“作用”的。当这个进程要操作消息队列、共享内存、信号量等对象的时候,其实就是在比较这个用户和组是否有权限。谁启动的进程就该审核启动的用户有没有这个权限。我们可以通过 chmod u+s program 命令,给这个游戏程序设置 set-user-ID 的标识位。创建的进程 uid 当然还是用户 A,但是 euid 和 fsuid 就不是用户 A 了,因为看到了 set-user-id 标识,就改为文件的所有者的 ID,也就是说,euid 和 fsuid 都改成用户 B 了。一个进程可以随时通过setuid设置用户ID。
linux中的最高权限是root,一般用户都是普通权限,可以引入capabileties,用位图表示权限
在 capability.h 可以找到定义的权限。我这里列举几个。


#define CAP_CHOWN            0
#define CAP_KILL             5
#define CAP_NET_BIND_SERVICE 10
#define CAP_NET_RAW          13
#define CAP_SYS_MODULE       16
#define CAP_SYS_RAWIO        17
#define CAP_SYS_BOOT         22
#define CAP_SYS_TIME         25
#define CAP_AUDIT_READ          37
#define CAP_LAST_CAP         CAP_AUDIT_READ
  • cap_permitted 表示进程能够使用的权限。
  • cap_inheritable,root下可以继承调用者的集合;非root用户的话通常不会保留
  • cap_bset,也就是 capability bounding set,是系统中所有进程允许保留的权限。
  • cap_ambient非 root 用户进程使用 exec 执行一个程序的时候,如何保留权限的问题。当执行 exec 的时候,cap_ambient 会被添加到 cap_permitted 中,同时设置到 cap_effective 中。

内存管理

每个进程都有自己独立的虚拟内存管理空间,这里需要一个数据结构来表示

struct mm_struct                *mm;
struct mm_struct                *active_mm;

文件与文件系统

每个进程有一个文件系统的数据结构,还有一个打开文件的数据结构。这个我们放到文件系统那一节详细讲述。


/* Filesystem information: */
struct fs_struct                *fs;
/* Open file information: */
struct files_struct             *files;

setuid是一个权限的特殊标志位,带有这个标志位可以对文件执行等同root的权限!比如,Linux下修改密码的指令passwd,我们ls去查看时发现其权限就有s标志,这个就是之所以能修改密码的原因。如果去掉这个权限,再以普通用户身份去修改密码则会提示没有权限!这个例子和老师的玩游戏可以说是异曲同工,但它更具有普遍性,大家也更熟悉!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值