13 | 进程数据结构(中):项目多了就需要项目管理系统

本文仅作为学习记录,非商业用途,侵删,如需转载需作者同意。

继续说task_struct 结构…

1.1、运行统计信息

参照员工工作情况,也需要了解进程的工作情况,例如进程在用户态、内核态消耗的时间,上下文切换次数等。

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

1.2、进程亲缘关系

任何一个进程都有父进程。

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 用于把当前进程插入到兄弟链表中

在这里插入图片描述

通常情况下,real_parent 和 parent 是一样的,例如:
1、bash创建了一个进程,那进程的parent和real_parent就都是bash
2、bash上使用GDB来debug一个进程,这个时候GDB是parent,bash是这个进程的real_parent

1.3、进程权限

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

权限:我能操纵谁,谁能操纵我

操作者是:Subjective
被操作对象:Objective

“操作” 需要操作者和被操作者双方权限认证。
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;

上面大部分是:关于用户和用户组的信息

uid和gid:注释是real user/group id 。一般情况下,谁启动的进程,就是谁的id。 在权限审核的时候,这2个基本不起作用。

euid和egid:注释是effective user/group id。 当这个进程要操作消息队列、共享内存、信号量等对象的时候,就是在比较这个用户和组是否有权限。

fsuid和fsgid filesystem user/group id 。 这个是对文件操作会审核的权限。

一般来说,fsuid、euid和uid 是一样的
fsgid、egid和gid 也是一样的。

因为谁启动的进程,应该审核启动的用户到底有没有这个权限。

在这里插入图片描述

上图中的第一个和第二个流程比较容易理解。

第三个不能保存怎么解决呢?

通过chmod u+s program 命令,给这个游戏程序设置 set-user-id 的标识位,把游戏的权限变成 rwsr-xr-x 。
这个时候用户A 再启动这个游戏的时候,创建的进程 uid 当然还是用户A ,但是euid 和 fsuid 就不再是用户A了,因为看到了 set-user-id 标识,就改为文件所有者的id,也就是说 euid 和 fsuid 都改成用户B 了,这样游戏文件就能保存下来了。


capabilities 更细粒度的权限,用位图表示权限,在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_effective。

cap_permitted 中可以包含 cap_effective 中没有的权限。

一个进程可以在必要的时候放弃自己的某些权限,这样更加安全,如果因为代码漏洞被攻破了,啥也干不了,就没法进一步突破。

cap_bset : capaility bounding set 。 是系统中所有进程允许保留的权限,如果这个集合中不存在某个权限,那么系统中的所有进程都没有这个权限。即使以超级用户权限执行的进程也是一样的。

其中的一个好处是:系统启动以后,将内核加载的权限去掉,那所有进程都不能加载内核模块,这样即使这台机器被攻破了,也做不了太多有害的事情。

cap_ambient 是比较新加入内核的,就是为了解决cap_inheritable 鸡肋的状况。
也就是非root用户进程使用 exec 执行一个程序的时候,如何保留权限的问题。
当执行 exec的时候,cap_ambient 会被添加到 cap_permitted 中,同时设置到cap_effective中。

1.4、内存管理

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

struct mm_struct                *mm;
struct mm_struct                *active_mm;

1.5、文件与文件系统

每个进程都有一个文件系统和打开文件的数据结构:

/* Filesystem information: */
struct fs_struct                *fs;
/* Open file information: */
struct files_struct             *files;
总结时刻
  • 进程亲缘关系维护的数据结构,是一种很有参考价值的实现方式,内核中多个地方用到这个数据结构
  • 进程权限中的setuid 的原理,比较重要,面试经常会考

在这里插入图片描述

评论

RCU(Read-Copy Update) :随意读,更新数据的时候,先复制一份副本,在副本上完成修改,再一次性的替换旧数据。Linux 内核实现的一种针对“读多写少 ”的共享数据的同步机制。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值