Linux 进程概念 进程状态 fock函数讲解
PID和PPID
我如果想获取自己的PID呢?
pid_t getpid(void);
头文件:#include<sys/types.h> #include<unistd.h>
返回调用这个函数的进程ID(自己的PID)
PID一般会变化
如何获取PPID?
pid_t getppid(void);(父ID)
头文件:#include<sys/types.h> #include<unistd.h>
返回调用这个函数的进程ID(自己的PPID)
PPID在一次登录中不会变化
通过系统调用创建进程-fork初始
fork函数的调用
fork的英文名为分叉,
返回值:
子进程返回值为0,父进程返回子进程的PID
示例代码:
int main()
{
printf("before:only one line\n");
fork();
printf("after:only one line\n");//fork()之后的代码会被执行两次
//fork之前有一个执行流,fork之后就会变成两个进程
}
如何验证?
int main()
{
pid_t id = fork();
if (id == 0)
{
while (1)
{
printf("我是子进程,pid= %d,ppid= $d\n", getpid(), getppid());
sleep(1);
}
}
else if (id > 0)
{
while (1)
{
printf("我是父进程,pid= %d,ppid= $d\n", getpid(), getppid());
sleep(1);
}
}
else
{
//error
}
}
运行结果
说明fork创建了父子进程,并且fock之后父子进程的代码是共享的。
创建子进程
1.创建子进程PCB
2.填充PCB对应的内容
3.让子进程和父进程指向同样的代码
4.父子进程都是有独立的task_struct,可以被CPU调度运行。
fork的常见问题
- 为什么fork要返回两个值;也就是说为什么子进程返回值为0,父进程返回子进程的PID?
返回不同的返回值是为了区分让不同的执行流,执行不同的代码块。
为什么父进程返回子进程的PID:想要通过父进程要明确控制的是哪一个子进程
- 一个函数是如何做到返回两次的?如何理解?
return 语句也是代码,所以return语句就被父子共享,所以父进程在执行时返回一次,子进程在执行时返回一次,所以最后就被反悔了两次。
- 一个变量怎么会有不同的值?如何理解?
- 这里要引入一个概念:几乎在任何平台,进程在运行的时候,是具有独立性的。
- 所有有了独立性,父子进程就绝对不能访问同一份数据,因为数据可能被修改,所以不能让父子进程共享同一份数据。但是之前说父子进程代码是共享的,该怎么理解?共享代码并不影响独立性。
当子进程要修改父进程数据时,操作系统就会给子进程开辟一款新空间,让子进程来使用,不影响父进程的数据,但是不修改时,就不会开辟。这叫做:数据层面的写时拷贝
- 为什么要创建子进程?
为了让父和子进程执行不同的代码块。所以让fock具有了不同的返回值。
- 如何父子进程被创建,往后是谁先运行呢?
谁先运行,有调度器决定,谁先运行是不确定的。
进程状态
运行状态
- 运行队列
多个进程由双链表维护,当操作系统找到整个队列的头部head,我们就能调度某个进程,把这个进程的代码和数据放在CPU上运行。可是进程是相当多的,但是CPU只有一个,所以进程就会竞争CPU资源。所以每个进程都会维护一个运行队列。里面包含了struct task_struct *head;和 struct task_struct *tail;到了谁就去执行谁。凡是处于运行队列的进程,他们所处状态叫做运行态或者R状态(我已经准备好了,随时可以被调度的状态)
- 一个进程只要把自己放到CPU上开始运行了是不是就一直要执行完毕,才把自己放下来?
不是的。每个进程都有一个叫做:时间片(10ms)的概念,当当前进程运行超过某个时间段(比如说10ms左右),就会重新放到队列尾部重新排队。放上去,拿下来的操作,这叫做进程切换。在一个时间段内,所有进程代码都会被执行,这叫做并发执行。
阻塞状态
- 什么叫做阻塞状态?
如果某个进程要从键盘读取数据,当要输入数据时,我们故意不输入任何数据时,此时进程会一直等待输入。所以这个进程就不在运行队列中,而是在等待队列中,去等待键盘的输入。所以当某个进程要读取数据,但是却不输入数据,会在等待队列中等待,我们把这种等待某种特定设备的这种进程,称之为该进程处于阻塞状态。
- 操作系统如何管理各种硬件?
先描述 再组织
挂起状态
- 什么叫做挂起
假设现在有一个磁盘,此时进程处于阻塞状态等待时,突然在等待时,如果操作系统的内存资源严重不足了,操作系统就得保证正常的情况,就要腾出内存资源,此时操作系统就会将进程的PCD继续保留在内存中,代码数据保存到外设磁盘中这个过程叫换出,这个状态称为阻塞挂起状态。等有数据输入时,操作系统又会将保存在磁盘中的代码数据重新迁移到内存中这个过程叫换入。
常见问题
- 运行队列和等待队列在哪里?
全部在内存当中。在内存的任意位置。
- 主动运行一个进程,是在排队等待呢?还是直接运行呢?
大概率是需要等待,但是CPU速度非常快,我们几乎感觉不到等待。