Linux进程概念

目录

  • 操作系统:linux
  • 进程:
    • 进程概念
    • 进程操作
    • 进程状态
    • 环境变量
    • 程序地址空间
    • 内存管理方式

硬件结构决定了软件行为:
Linux进程概念_第1张图片
程序运行,会被加载到内存中
因为程序要想被执行,就需要放在内存中被cpu进行读取处理。
例如:
qq聊天实现:键盘采集输入,放到内存,cpu进行处理,网卡发送数据

操作系统:linux

组成:内核+应用
定位:计算机上搞管理的软件,管理计算机上的软硬件资源
管理:

                      用户
                     库函数
                  系统调用接口
  			   	 操作系统  内核
  					硬件驱动
  				 键盘,鼠标....硬件

Linux进程概念_第2张图片

系统调用接口:操作系统提供的用户访问系统内核的接口
库函数与系统调用接口的关系:库函数实际上就是对系统调用接口进行的一层封装后的接口

进程:

进程概念

进程:运行中的程序
pcb:进程控制块:程序运行的描述
通过程序的运行描述,操作系统就可以调度哪个程序可以占用cpu去运行指令,要运行哪个程序,则操作系统找到对应程序的pcb,在pcb取出程序的运行所需信息,加载到cpu上,cpu就开始运行这个程序了。

对于操作系统来说,进程就是一个程序运行的描述,通过这个描述,操作系统可以进行程序的调度运行管理。
实际上对于系统来说,进程就是pcb
这个程序运行的动态描述,叫做pcb进程控制块,在Linux下是一个task_struct结构体。

描述信息:内存指针,上下文数据,程序计数器,进程ID-pid,IO信息,进程优先级,进程状态,记账信息…

时间片:cpu调度运行程序的时间段
时间片过后,就该切换调度下一个进程了

并发:一种轮询处理的方式
并行:同时运行

进程操作

进程的简单操作:
创建进程:进程就是一个pcb是一个task_struct结构体(linux中),创建一个进程实际上就是创建了一个task_struct结构体
pid_t fork(void) --创建进程的接口–通过复制调用这个接口的进程(父进程),创建一个新的进程(子进程)

#include
#include
#include

//子进程睡眠5秒退出,父进程继续进行,陷入死循环
int mian(int argc, char *argv[])
{
	printf("-------");
	pid_t pi = fork();
	//子进程复制了父进程,因此往后的代码父进程都会运行,但是因为返回值不同因此进入不同的if
	if(pid < 0)
	{
		//出错了
	}
	else if(pid == 0)
	{
		//子进程--对于子进程返回值是0
		sleep(5);
		exit(0);	//退出进程--谁调用就退出谁	
	}
	else
	{
		//父进程--对于父进程返回的是子进程的pid,因此返回值是大于0
	}
	printf("hello:%d\n", getpid());
	while(1)
	sleep(1);
	return 0;
}

ps -ef :查看所有进程信息
ps -ef | grep fork :查找指定字符(fork)的进程信息
ps -aux | grep fork:更详细信息

进程状态

进程状态:用于操作系统对于进程的管理(什么状态对进程进行什么样的操作)
运行态,就绪态,阻塞态
linux中的进程状态:
运行态(R):正在运行或者轮转到时间片能够运行统称运行态
可中断休眠态S:可以被中断的休眠状态(满足唤醒条件,或者休眠被中断则进入运行态)
不可中断休眠态D:不能被中断的休眠状态(满足唤醒条件之后才会进入运行态)
停止态T:程序停止运行的状态(依然会被调度,但是什么都不做)
死亡态X
僵尸态Z:进程已经退出了不再调度了,但是这个进程的资源还没有被完全释放,等待处理的一种状态。
僵尸进程:处于僵尸态的进程,是一种退出,但是资源没有完全被释放的进程
产生:紫禁城先于父进程退出,但是父进程没有关注到子进程的退出,因此资源不会完全释放子进程的资源,这个子进程进入僵尸状态。
子进程退出之后,在进程pcb中保存了自己的退出返回值,在父进程没有关注处理的情况下,pcb资源是不会被释放
危害:资源泄露(一种是pcb所占的内存资源一直无法被回收,一种是一个用户所能创建的进程数量是有限制的)
解决方案:
处理:退出父进程
避免:进程等待
孤儿进程:父进程先于子进程退出,子进程就会成为孤儿进程,运行在后台,父进程称为1号进程(早期名字叫init进程,后期叫systemd)
精灵进程(守护教程):

环境变量

环境变量:保存运行环境参数的变量;使程序运行环境配置更加灵活;以及可以通过环境变量实现进程间的小量通信(父子进程的传递)
命令操作:env(查看环境变量),set(查看所有变量),echo(查看指定变量),export(声明或设置环境变量),unset(删除变量)
典型环境变量:
PATH:程序运行的默认搜索路径—在命令行终端中输入命令名称可以直接执行对应名称的命令程序,实际上是因为shell扑捉到输入的命令名称之后,然后去PATH环境变量指定的路径下去找这个程序,找到了就运行,找不到就报命令没有找到的错误。

环境变量接口:
char *getenv(const char *name);—通过名称获取值;
铺垫:shell中运行的程序,父进程都是shell;或者反过来说,shell中运行的进程都是shell的子进程
代码操作:getenv()、**extern char environ; 、main(int argc, char *argv[], char *env[])

程序地址空间

程序地址空间:
地址:通常所说的地址,都是内存的地址,是内存单元的编号
实际上在进程中,程序访问的这些地址(变量地址…)实际上是一个假地址
将其称之为–虚拟地址;
我们所说的程序地址空间实际上叫做进程的虚拟地址空间
虚拟地址空间实际上是系统给进程所描述的一个假的地址空间,是一个mm_struct结构体
系统会为每一个进程都描述一个假的地址空间,进程访问的都是虚拟地址,访问内存数据的时候,先将虚拟地址转换成物理地址然后访问

系统为每个进程都描述一个完整的,连续的,线性的虚拟地址空间,实际物理内存用的时候再给进程分配。这样的话,对于每个进程自己的感觉,看起来都有一块完整的,连续的内存可以使用。

虚拟地址空间,是系统为每个进程通过mm_struct结构体虚拟的一个地址空间,使用虚拟地址空间的目的是为了让进程能够访问一块连续的,完整的地址,并且经过页表映射到物理内存之后,可以实现数据在物理内存上的离散式存储,提高内存利用率,并且在页表中可以进行内存访问控制

虚拟地址如何通过页表获取物理地址的呢?

内存管理方式

  • 分段式内存管理:将地址空间分为多段(代码段,数据段…)便于编译器进行地址管理

分段式虚拟地址组成:段号+段内的地址偏移量;在系统中有一个段表:一个个段表项(段号,物理内存段起始地址)

  • 分页式内存管理:将地址空间分为多个小块(页),提高内存利用率

分页式虚拟地址组成:页号+页内偏移;在系统中有一个页表(页号,物理内存快起始地址,权限控制,缺页中断位…)
4G(2^32 )内存;内存页大小4k(1k是1024,为2^10 ; 4k为2^12)
所以内存大小除以内存页大小,一共有2^20个内存页
因此32位内存地址,搞20位就是页号,低12位就是页内偏移

  • 段页式内存管理:将虚拟地址进行分段,在每个分段内进行分页式管理,集合了分段分页的优点进行内存管理

你可能感兴趣的:(linux,服务器)