linux学习

一个可执行程序包含三个部分:

代码段:存放指令,操作以及只读的数据

数据段:全局或者静态变量

管理程序所以创建进程,一个进程是执行的程序段,

进程:一个程序在执行时所创建的用来管理这个程序的东西,在内核中会创建一个pcb,即为进程控制块,其实就是一个结构体,用来管理这个程序的所有的资源。

程序一般存储在磁盘上,我们执行一个程序,是在内存中执行,那么首先将磁盘中的程序移到内存中,并且一一对应起来,便在内存中就有相应的代码段、数据段、和BSS段,与磁盘相比较而言,多了什么东西呢,多了堆段和栈段。

进程时unix/linux中基本的资源管理单元。

进程是执行的代码片段(一个程序可以创建多个进程,一个进程可以执行多个程序的代码)。

将一个代码片段加载到内存让其执行也就创建了一个(后续创建多个)进程。

进程与程序之间的关系,程序存储在磁盘上,是一个文件,而一个进程是加载到内存的程序段是动态的,且有生命周期,创建、执行、退出、等待的状态。

一个进程肯定不仅仅是占用了加载代码的内存,在linux下,使用task_struct来维护进程,在内核中描述进程就用的这个结构体。在这个结构体中一般有进程的状态、与内存相关的东西,堆、栈、以及这个进程打开的文件,struct file *fd_array[NR_OPEN_DEFAULT]这个结构体里面存放的就是文件描述符,还有一些是文件系统的信息、信号相关的内容。

volatile long state; /*-1 unrunnable,0 runnable,0 stopped*/

struct mm_struct *mm;与存储相关。描述了在用户空间中,代码段,数据段,堆,栈,mmap等设计的所有内存信息。

structfiles_struct *files;打开的文件列表,成员 struct file *fd_array[NR_OPEN_DEFAULT]描述了这个进程打开的文件列表。

进程的资源管理(创建、管理)

PID:进程号,每个进程有唯一的编号。

state:linux 是多任务多用户、cpu在各个执行单元中不停的跳转。某个进程需要等待其他的资源时,cpu转而执行其他的进程,充分利用了cpu的资源,在什么时候执行哪一个进程实质是由调度算法来决定的。

运行状态:占有资源、执行

就绪状态:除了cpu之外,其他资源都已经获取,等待调度算法来调度执行。

等待状态:除了cpu之外,还要等待其他资源或者时间,可中断等待(可以被信号打断)和不可中断等待。

停止状态:正在被跟踪或者调度的进程用户。

僵死状态:用户资源已经回收,pcb内核资源没有回收,已经不能执行。

划分进程:

创建进程时,一个比较独立的任务(事务)就创建一个进程,这个事务尽量不与其他事物有太多的交融(耦合性)。

进程的生命周期与进程资源的管理,api应用。

创建:进程创建与进程资源获取,fork/vfork。在进程创建过程中,实际上执行的操作时将程序的代码段、数据段、BSS段从磁盘加载到内存,并且申请堆栈空间。

内核空间中:为这个进程分配唯一的PID标识,同时,在内核中为这个进程申请控制块PCB,初始化相关的信息。

在运行过程中,涉及打开的文件,关联的终端,安装信号,状态等系列信息。

在创建进程时,是由父亲进程来创建新的子进程。fork函数

pid_t fork(void)

在父亲进程中,返回子进程的ID,在子进程本身,返回0.

进程中执行新代码

在进程执行过程中,要执行新的代码,实际上我们创建一个新进程,更多的时期望在这个进程中执行新的代码,而不是原来的代码。

在子进程中,替换了原有进程的代码段和数据段()

  #include <unistd.h>

       extern char **environ;

       int execl(const char *path, const char *arg, ...);
       int execlp(const char *file, const char *arg, ...);
       int execle(const char *path, const char *arg,
                  ..., char * const envp[]);
       int execv(const char *path, char *const argv[]);
       int execvp(const char *file, char *const argv[]);
       int execvpe(const char *file, char *const argv[],
                   char *const envp[]);

   进程退出:

(1)被别人kill掉,kill一个命令,kill -9 pid

(2)显示的执行exit系列函数,exit

3)进程遇到main函数的,没有代码可以执行,或者,main函数return。

exit与return的区别

exit是一个系统调用函数,是退出这个进程,return是c关键字,退出这个函数。

exit()在退出时会对进程资源做清理,例如刷新流的缓冲区,而_exit()不做任何处理,直接退出。

进程资源回收:

进程退出有退出的状态,另外,进程资源的回收在exit的时候仅仅是释放了它的用户空间资源,而内核空间资源PCB没有回收,转而由它的父亲进程通过wait相关的函数来回收。

子进程在退出时会给父亲进程发送一个信号,父亲进程可以显式的调用wait/waitpid等待子进程结束并回收资源。

回收资源时也可以得到子进程退出的状态。

总结资源申请与释放的问题:

创建时,申请进程所有的资源,内核中PCB,用户空间加载代码数据段,申请堆栈空间,运行时,打开的文件,安装的信号,关联的终端等。

执行新代码时,替换代码段,数据段,bss段,堆栈空间信息等用户空间信息,但是内核PCB的信号没有改。

退出时,释放了自己用户空间的资源(代码段,数据段,bss段,堆、栈,关联所有内存信息),但是没有回收PCB。

进程 已经退出,但是没有回收内核PCB资源的进程叫僵死进程。

父亲进程先于子进程推出的,这个子进程就是孤儿进程,父亲进程会被转移为init这个进程

进程创建详解与父子进程资源:

父子进程执行顺序问题:

父子进程在创建完子进程后互不关联,以独立身份抢占CPU资源,具体谁先执行由调度算法决定,用户空间没有办法干预,子进程执行代码的位置时fork/vfork函数返回的位置。

 

 

字资源申请问题

子进程重新申请新的物理内存空间,复制复习呢进程地址空间所有的信息(当然,现在的操作系统实际采用写实复制等策略,真正的物理内存空间发生在需要写入时)

子进程复制父亲进程的代码段,数据段,bss段,堆栈,所有用户空间的信息,在内核中操作系统为其重新申请一个PCB,并且使用父亲进程的PCB来出事化,除了pid等特殊信息外,几乎所有的信息都是一样的。

流的缓冲区会刷新没有刷新的信息,且缓冲区在用户空间中,虽然子进程创建

 

 

execx后资源问题:

在execx系列函数替换代码后,对打开的文件能够在处理莫?

默认情况下,exec执行的代码中可以访问在原来代码中打开的文件,操作时同一个文件描述符,即同一个文件对象。

进程属性管理:

进程的属性包括进程组属性和用户属性:

进程组属性决定了进程在运行过程中控制权限以及相关控制信息。

PID:进程号,当前进程在当前系统下唯一的编号,针对这个进程执行的操作多以进程号为标识。

用户可以获取getpid(),但是不能通过相关函数来修改。

PPID:父亲进程号,一般为创建这个进程的那个进程的ID,一般不会修改,当这些进程的父亲进程退出后,当前进程变成孤儿进程,它的PPID会被修改为intit进程,即为PID=1的这个进程。

PGID:进程组号,将完成协同工作的多个进程默认为一个进程组,例如,在终端运行一个新的程序,新程序创建的子进程以及自身在一个进程组下,而第一个进程默认为进程组长,进程组号也是进程组长的ID

getpid(()//参数为某个进程的ID,返回该进程的进程组长编号。

setpgid(pid,pgid)//修改某个进程的进程组长。

修改一个进程的进程组号的意义,kill可以向一个进程组发起信号,要影响整个这个进程组的所有进程。

SID:会话ID。进行交互,在某个终端下执行的程序所创建的进程/进程组,它们的sid就是这个终端进程 的编号,在一个会话下的所有进程都将搜到这个会话终端的影响。

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值