linu学习笔记--进程基础
Posted 水澹澹兮生烟.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linu学习笔记--进程基础相关的知识,希望对你有一定的参考价值。
Linux进程
1.冯诺伊曼体系结构
1.1体系结构示意图
计算机的基本硬件是由运算器,控制器,存储器,输入和输出设备5大部件组成。运算器和控制器等部件被集成在一起称之为中央处理器(CPU)。
1.2重要思想
a.所有数据采用二进制存储–>契合电路的特性
b.数据都保存在存储器中
2.操作系统
操作系统的本质是一组程序,他管理和控制这其他程序的执行,并且充当应用程序和设计计算机硬件的接口,操作系统是描述和组织计算机当中软硬件资源的软件,操作系统=计算机内核+应用。(计算机内核就是某种操作系统的代码的统称。)
2.1linux操作系统内核
与UNIX系统相似,linux系统大致分为三层:
- 靠近硬件的底层是内核,即linux操作系统常驻内存部分。
- 中间层是内核之外的shell层,即操作系统的系统程序部分。
- 最高层是应用层,即用户程序部分。
内核是操作系统得到主要部分,它实现进程管理,内存管理,文件系统,设备驱动和网络系统等功能,从而为核外的所有程序提供环境。
2.2系统调用
一般类来说,可以将操作系统划分为内核和系统程序两部分,系统程序及其所有程序在其内核上运行,他们与内核之间的皆空由操作系统提供的一组"抽象指令"定义,这些抽象指令称之为系统调用。
3.进程管理
3.1进程和程序的区别
程序:本质上就是一个文件,是静态的,存储在磁盘中;
进程:程序运行起来称之为进程,是动态的,由操作系统管理。简单的说,进程就是程序运行的一次过程,进程的动态性质是由其状态变化决定的。
3.2从内核的角度看进程
描述:Linux系统中每个进程都有一个名为task_struct{…};的数据结构。它相当于一个"进程控制块"(PCB)。
组织:双向链表组织的。
task_struct结构包含的信息:进程状态,调度信息,标志符,内部进程信息,链接信息,时间和计时器,文件系统,虚拟内存和处理信息。
进程PID:进程号,在当前操作系统当唯一标识一个进程
3.3进程状态
如何查看当前操作系统中所有的信息:ps aux/axj
如何查看刚刚的进程:ps aux | grep pross_test
运行态:正拿着CPU资源进行运算的进程所持有的状态;
就绪态:一切的准备资源就绪了,等待操作系统分配CPU资源;
阻塞态:等待某种资源来到之后,才能运算。
细分状态:
- R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
- S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
- D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
- T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT信号让进程继续运行。
- X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
- Z僵尸状态(zombie):僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
内存指针:保存了程序地址空间的首地址
3.4进程切换
1.与进程切换具有强相关的两个概念:程序计数器和上下文信息
程序计数器:保存了进程即将要执行的一条指令(汇编指令)
上下文信息:保存了程序运行的寄存器当中的内容
2.I/O信息
操作系统使用了PCB描述了启动的进程信息,他同时也在磁盘当中为正在运行的进程创建了一个文件夹,文件夹的命名是以进程号(PID)命名的。这也文件都保存在/proc/][pid]/fd里面。
3.记账信息
cpu的使用率,内存的使用率,cpu使用时长。
4.folk创建进程
4.11fork函数
- pid_t fork(void);
当返回值小于零时,返回失败;
当他小于零时,创建失败了;
等于零时:返回给子进程;
当大于零时,返回给父进程的,返回大于零的值就是子进程的PID。
- getpid();
谁调用返回谁的进程号
- getppid();
谁调用返回谁的父进程号
在这里我们要理解几个问题:
- 父进程先运行还是子进程先运行?
a.子进程被创建出来后,在内核当中是一个PCB,被挂在双向量表当中组织起来的。
b.父进程还是子进程先运行这个是不确定的,取决于操作系统的调度。
c.两个进程之间是抢占式执行。使用fork()创建出来的子进程,父子进程在执行期间也是抢占式执行的。
- 子进程在创建出来之后还会有什么关系吗?
无关。
- 子进程创建出来后,代码是从哪里开始执行的,为什么?
从fork()之后。
原因:
- 在命令行解释器当中启动一个进程,该进程的父进程是谁?
bash–>命令行解释器(shell)
4.2僵尸进程
4.2.1代码实现
模拟原则:
a.在代码中创建出来一个子进程
b.模拟让子进程先于父进程退出
运行,观察子进程当前的运行状态。
//僵尸进程
#include<stdio.h>
2 #include<unistd.h>
3
4 int main(){
5 pid_t pid = fork();
6 if(pid < 0){
7 perror("fork");
8 return 0;
9 }
10 else if(pid == 0){
11 //child
12 printf("i am child,pid:%d,ppid:%d\\n",getpid(),getppid());
13 }
14 else{
15 //father
16 while(1){
17 printf("i am father,pid:%d,ppid:%d\\n",getpid(),getppid());
18 sleep(1);
19 }
20 }
21 return 0;
22 }
4.2.2僵尸进程的危害
僵尸进程的来源:父进程创建处一个子进程,子进程先于父进程退出,子进程在推出的时候回想父进程发送一个信号(SIGCHLD),而父进程对于该信号并没有对其处理,导致子进程在退出时没有进程来回收子进程的资源。
终止进程的两个命令:
kill [pid]
kill -9 [pid] (强杀命令)
当我们用ps命令能够查看当前进程的时候,说明此时描述这个进程的task_struct结构体在操作系统内核中还是存在的,这时我们我们用kill命令不能将僵尸进程中断掉,说明此时我们不能将这个结构体从内核中释放掉,若此时不能进行释放掉,那此时就会造成内存泄漏。
4.2.3解决方案
- 重启操作系统(不推荐)
- 进程等待
- 将僵尸进程父进程删掉,让1号进程领养回收他的PCB
4.3孤儿进程
模拟规则:
父进程创建一个子进程,父进程先于子进程退出,子进程就是孤儿进程。
#include<stdio.h>
#include<unistd.h>
int main(){
pid_t pid = fork();
if(pid < 0){
perror("fork");
return 0;
}
else if(pid == 0){
//child
while(1){
printf("i am child,my pid:%d,my ppid:%d\\n",getpid(),getppid());
sleep(1);
}
}
else{
//father
printf("i am father,pid:%d,ppid:%d\\n",getpid(),getppid());
}
return 0;
}
孤儿进程:父进程变成了1号进程,当子进程的父进程先于子进程退出时,子进程会被1号进程所领养,1号进程被称为init进程。孤儿进程被1号进程所领养后变成了一个后台进程。
5.环境变量
5.1环境变量的作用
环境变量一般是指在操作系统中用来制动操作系统运行环境的一些参数。
5.2常见的环境变量
PATH:指定可执行程序的搜索路径
HOME:指定用户的祝工作目录(即用户登录linux系统中时默认的目录)
SHELL:当前shell,他的值通常时/bin/bash 。
5.3环境变量的文件
系统级别的: /etc/bashrc (不推荐直接更改这个文件)
用户级别的: ~./bashrc
~./bash_profile(推荐大家在更改时使用这两个文件)
5.4查看环境变量
a.使用echo查看环境变量
b.env
5.5修改环境变量
命令方式:export 环境变量名称=$环境变量名称:新添加环境变量的值
临时修改:直接在命令行中执行修改命令,只针对当前终端有效,当前终端重启后们也就失效了
永久修改:将修改命令直接写到环境变量文件中,使用source[环境变量文件]使其立即生效
$source ~/.bash_profile (对文件重新加载一次)
5.6环境变量的组织方式
它是一个指针数组,他的最后一个元素以NULL结尾。
6.虚拟地址空间
6.1进程虚拟地址空间&它和内存指针的关系
我们在c/c++代码当中使用的&获得的地址,都是操作系统中虚拟出来的地址,而并非内存条中的物理地址。虚拟地址的产生,是由于操作系统为了方便统一管理物理内存诞生的。虚拟地址并不能够保存数据,保存数据还是在物理内存当中保存的。所以,当一个进程在使用虚拟地址访问数据的时候,操作系统需要通过虚拟地址找到物理地址,从而促使进程访问数据内存指针指向进程虚拟地址空间。
6.2虚拟地址转化成物理地址
a.分页式
在分页式当中,虚拟地址=页号+页内偏移。页号=虚拟地址/页的大小;页内偏移=虚拟地址%页的大小。
b.分段式
虚拟地址=段号+段内偏移
c.段页式
虚拟地址=段号+页号+页内偏移
7.并行和并发
并行:多个进程同时拥有不同的CPU进行运算,称之为并行。
并发:多个进程在同一时刻只能由一个进程拥有CPU进行运算,称之为并发。
进程的独立性:多进程运行,需要独享各种资源,多进程运行期间互不干扰。
以上是关于linu学习笔记--进程基础的主要内容,如果未能解决你的问题,请参考以下文章