既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
任务 ID
每一个任务都应该有一个 ID,作为这个任务的唯一标识。task_struct 里面涉及任务 ID 的如下:
pid\_t pid; //process id线程
pid\_t tgid; //thread group ID 进程的主线程
struct task\_struct \*group_leader; //进程的主线程。
- 进程和线程到了内核这里,统一变成了任务,用
ps
就可以展出所有点进程。 - 给任务下发指令
kill
可以杀死进程 ,但是杀了线程却杀不死进程。
信号处理
task_struct 里面关于信号处理的字段.
/\* Signal handlers: \*/
struct signal\_struct \*signal; // 指向shared\_pending 线程组共享的。
struct sighand\_struct \*sighand; // 正在通过信号处理函数进行处理
sigset\_t blocked; // 阻塞暂不处理
sigset\_t real_blocked;
sigset\_t saved_sigmask;
struct sigpending pending; // 等待处理 本任务的
unsigned long sas_ss_sp; // 开辟新的栈专门用于信号处理 (最后这三个变量)
size\_t sas_ss_size;
unsigned int sas_ss_flags;
任务状态
在 task_struct 里面,涉及任务状态的是下面这几个变量:
volatile long state; /\* -1 unrunnable, 0 runnable, >0 stopped \*/
int exit_state;
unsigned int flags;
//state(状态)可以取的值定义在 include/linux/sched.h 头文件中。
/\* Used in tsk->state: \*/
#define TASK\_RUNNING 0 //表示进程在时刻准备运行的状态 如果有进程就运行 没有就等
//在运行中的进程,一旦要进行一些 I/O 操作,需要等待 I/O 完毕,这个时候会释放 CPU, 进入睡眠状态。
#define TASK\_INTERRUPTIBLE 1 //可中断的睡眠状态 (根据信号决定)
#define TASK\_UNINTERRUPTIBLE 2 // 不可中断的睡眠状态 (一直等IO完成)
#define TASK\_KILLABLE (TASK\_WAKEKILL | TASK\_UNINTERRUPTIBLE) // TASK\_KILLABLE,一种新的进程睡眠状态 可以终止的新睡眠状态 TASK\_WAKEKILL 用于在接收到致命信号时唤醒进程
#define \_\_TASK\_STOPPED 4 //收到 SIGSTOP、SIGTTIN、SIGTSTP 或者 SIGTTOU 信号之后进入该状态。
#define \_\_TASK\_TRACED 8//表示进程被 debugger 等进程监视,当一个 进程被另外的进程所监视,每一个信号都会让进程进入该状态。
/\* Used in tsk->exit\_state: \*/
#define EXIT\_DEAD 16//EXIT\_DEAD 是进程的最终状态
#define EXIT\_ZOMBIE 32 // exit\_state。
#define EXIT\_TRACE (EXIT\_ZOMBIE | EXIT\_DEAD)
/\* Used in tsk->state again: \*/
#define TASK\_DEAD 64 // exit\_state。
#define TASK\_WAKEKILL 128
#define TASK\_WAKING 256
#define TASK\_PARKED 512
#define TASK\_NOLOAD 1024
#define TASK\_NEW 2048
#define TASK\_STATE\_MAX 4096
//标志 : 放在 flags 字段中,这些字段都被定义称为宏,以 PF 开头。
#define PF\_EXITING 0x00000004 //PF\_EXITING表示正在退出
#define PF\_VCPU 0x00000010 // PF\_VCPU表示进程运行在虚拟 CPU 上。在函数 account\_system\_time 中, 统计进程的系 统运行时间
#define PF\_FORKNOEXEC 0x00000040 //PF\_FORKNOEXEC表示 fork 完了,还没有 exec(以新的进程去代替原来的进程,但进程的PID保持不变)
进程调度
进程的状态切换往往涉及调度,下面这些字段都是用于调度的, 看注释即可
// 是否在运行队列上
int on_rq;
// 优先级
int prio;
int static_prio;
int normal_prio;
unsigned int rt_priority;
// 调度器类
const struct sched\_class \*sched_class;
// 调度实体
struct sched\_entity se;
struct sched\_rt\_entity rt;
struct sched\_dl\_entity dl;
// 调度策略
unsigned int policy;
// 可以使用哪些 CPU
int nr_cpus_allowed;
cpumask\_t cpus_allowed;
struct sched\_info sched_info;
运行统计信息
//进程的运行过程中 运行情况的变量
u64 u64
utime;// 用户态消耗的 CPU 时间 stime;// 内核态消耗的 CPU 时间
unsigned long unsigned long
u64 u64
nvcsw;// 自愿 (voluntary) 上下文切换计数 nivcsw;// 非自愿 (involuntary) 上下文切换计数 start\_time;// 进程启动时间,不包含睡眠时间 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 \*/
如果在 bash 上使用 GDB 来 debug 一个进程,这个时候 GDB 是 real_parent,bash 是这个进程的 parent。
- parent 指向其父进程。当它终止时,必须向它的父进程发送信号。
- children 表示链表的头部。链表中的所有元素都是它的子进程。
- sibling 用于把当前进程插入到兄弟链表中。
进程权限
在 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;
//Objective (客): 谁能操纵我 real\_cred
//Subjective(主) : 我能操纵谁 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。
- euid 和 egid: 当这个进程要操作消息队列、共享内存、信号量等对象的时候,其实就是在 比较这个用户和组是否有权限
- fsuid 和 fsgid: filesystem user/group id。这个是对文件操作会审核的 权限。
游戏进程的 uid、 euid、fsuid 都是用户 A。第二个图,只有r x,只能运行保存不了,可以通过
chmod u+s program
给这个游戏程序设置set-user-ID
的标识位,权限变成 rwsr-xr-x,然后用户 A 再启动这个游戏 的时候,创建的进程 uid 当然还是用户 A,但是 euid 和 fsuid 就不是用户 A 了,因为看 到了set-user-id
标识,就改为文件的所有者的 ID,也就是说,euid 和 fsuid 都改成用户 B 了,这样就能够将通关结果保存下来。
在 Linux 里面,一个进程可以随时通过 setuid 设置用户 ID,所以,游戏程序的用户 B 的 ID 还会保存在一个地方,这就是 **suid 和 sgid,也就是 saved uid 和 save gid。**这样就可 以很方便地使用 setuid,通过设置 uid 或者 suid 来改变权限。
除了以用户和用户组控制权限,Linux 还有另一个机制就是capabilities,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_bset,也就是 capability bounding set,是系统中所有进程允许保留的权限.
- cap_ambient 是比较新加入内核的,就是为了解决 cap_inheritable 鸡肋的状况
内存管理
每个进程都有自己独立的虚拟内存空间,这需要有一个数据结构来表示,就是 mm_struct
struct mm\_struct \*mm;
struct mm\_struct \*active_mm;
文件与文件系统
每个进程有一个文件系统的数据结构,还有一个打开文件的数据结构。这个我们放到文件系统那一节详细讲述。
/\* Filesystem information: \*/
struct fs\_struct \*fs;
/\* Open file information: \*/
struct files\_struct \*files;
小结 看图复述
用户态的执行和内核态的执行的连接需要变量
struct thread_info thread_info; 和 void *stack;
用户态函数栈
- 程序的执行往往是一个函数调用另一个函数。函数调用都是通过栈来进行的.
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
来进行的.
[外链图片转存中…(img-l9ONRpZ7-1715591610200)]
[外链图片转存中…(img-AFc4uy8I-1715591610200)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新