网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
目录
进程基本概念
书上的概念是,进程是程序的一个执行实例,正在执行的程序等。在内核的观点看,进程是承担分配系统资源(CPU时间,内存)的实体。
描述进程PCB
OS为了管理进程,将进程信息描述出来,放在一个数据结构中,可以理解为进程属性的集合。这个数据结构称为PCB(process control block),Linux操作系统下的PCB是: task_struct,task_struct是Linux内核的一种数据结构,是一个结构体。它会被装载到RAM(内存)里,task_struct中几乎包含了进程相关的所有属性信息。
操作系统将所有的进程控制块(task_struct)用双链表的形式组织链接起来。OS对进程的管理,转化成为了对进程信息的管理,先描述再组织。在内核里面将对进程的管理变为对双链表的增删查改。
task_ struct内容分类
1.标识符:描述本进程的唯一标示符,用来区别其他进程。
Linux中用pid来标识进程,每一个进程在运行起来后都有一个唯一的标识,就是pid。
2.状态:任务状态,退出代码,退出信号等。
3.优先级: 相对于其他进程的优先级。优先级本质是在资源有限的前提下,确立谁先访问资源,谁后访问资源的问题。
4.程序计数器: 程序中即将被执行的下一条指令的地址。
CPU的核心工作流程可以简单理解为:
a.取指令 b.分析指令 c.执行指令
CPU运行的代码都是进程的代码,它怎样知道取进程中的哪些指令?
在cpu中有一个eip寄存器,这个寄存器会保存当前正在执行指令的下一条指令的地址。这个寄存器通常称为PC指针。当进程不运行了,但是它没有跑完的时候,将eip里面的内容保存进pcb里。
5.内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。可以通过内存指针找到该进程相关的代码和数据。
6.上下文数据:进程在CPU上运行,CPU寄存器上会有很多临时数据,当进程运行完毕从cpu上剥离的时候,这些数据是需要被保存的,这些数据称为当前进程的上下文数据。
7.I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
8.记账信息:包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
通过系统调用创建进程-fork
在linux中使用fork函数创建子进程。
pid_t是ProcessID_Type的缩写,其实是宏定义的unsigned int类型。
fork返回值如果子进程创建成功给子进程返回0,父进程返回子进程pid,如果失败了给父进程返回-1。
从程序员的角度看fork之后父子进程共享用户代码,而用户数据各自私有一份。因为代码是只读的,不可以修改或写入,本质上是为了维护进程的独立性。
从操作系统角度看多了一个进程,多了一个内核数据结构task_struct,创建子进程,通常以父进程为模板。其中子进程默认使用父进程的代码和数据(写时拷贝)。
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("i am father: %d\n", getpid());
pid_t ret = fork();
if(ret == 0)
{
//child
while(1)
{
printf("i am child, pid:%d, ppid:%d\n", getpid(), getppid());
sleep(1);
}
}
else if(ret > 0)
{
//father
while(1)
{
printf("i am father, pid:%d, ppid:%d\n", getpid(), getppid());
sleep(1);
}
}
else
{
//出错
}
return 0;
}
可以通过getpid()函数查看进程pid,getppid()查看该进程父进程的pid。
进程状态
/\*
\* The task state array is a strange "bitmap" of
\* reasons to sleep. Thus "running" is zero, and
\* you can test for combinations of others with
\* simple bit tests.
\*/
static const char \* const task_state_array[] = {
"R (running)", /\* 0 \*/
"S (sleeping)", /\* 1 \*/
"D (disk sleep)", /\* 2 \*/
"T (stopped)", /\* 4 \*/
"t (tracing stop)", /\* 8 \*/
"X (dead)", /\* 16 \*/
"Z (zombie)", /\* 32 \*/
};
R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
S状态和D状态对比:
S状态称为休眠状态,这种状态是浅度休眠,大部分的情况都属于浅度休眠。所谓浅度休眠指的是这种状态是可以被唤醒的。它虽然是一种休眠状态,但是随时可以接收外部的信号,处理外部的请求(通知它处理,它会在一瞬间醒来处理请求),换句话说,浅度休眠可以对外部事件做出反应。
D状态是深度休眠,深度休眠的进程不可被杀掉,即便是操作系统也不行。D状态通常在访问磁盘这样的IO设备,进行数据拷贝的关键步骤上需要将进程设置为D状态。D状态什么时候结束呢?只能等D状态的进程自动醒来,或者是关机重启(甚至重启都有可能导致机器被夯住)。
不管是深度休眠还是浅度休眠本质上都是一种等待状态。
T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
t (tracing stop):进程在gdb调试的时候可能看到这个状态。
Z(zombie)-僵尸进程
进程退出的时候,会自动将自己退出时的相关信息写入进程的PCB中,供OS或者父进程读取。读取成功之后,该进程才算真正死亡(X状态)。当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵尸进程(Z状态)。
最后的话
最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!
资料预览
给大家整理的视频资料:
给大家整理的电子书资料:
如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
的技术提升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!