Linux系统下的进程

进程的概念:

  • 冯诺依曼体系结构:

    • 现代计算机应该具备哪些硬件设备?
      • 输入设备—键盘/鼠标
      • 输出设备—显示器
      • 运算器——CPU
      • 控制器
      • 储存器—内存
  • 硬件结构决定软件行为:数据流向

  • 所有的硬件都是围绕储存器来工作

  • 存储器指的都是内存

操作系统:

一款搞管理的软件
  • 与硬件进行交互,管理软硬件资源
  • 为上层应用提供良好的执行环境
  • 管理体系:管理者/被管理者
  • 管理就是管理者先将被管理者进行描述起来然后组织起来进行管理

什么是进程:

进程:运行起来的程序
  • 可执行程序都是躺在硬盘上

  • 一个程序运行起来被加载到内存当中执行就是进程

  • 操作系统要对进程进行管理

  • 操作系统对进程的描述:PCB(进程控制块)——linux下加struct task_struct

操作系统对进程做了哪些描述:

  • 标识符(pid) 操作系统给进程的ID
  • 状态 表示进程现在的状态
  • 内存指针
  • I/O状态信息
  • 记账信息 一个进程在CPU上运行的时间等信息
  • 优先级
  • 程序计数器——用于保存程序运行的下一条指令
  • 上下文数据——用于保存进程切换时寄存器上的数据
  • 我们现在操作系统都是多任务多用户操作系统

  • 分时机制(其实同一时间只有一个进程在运行,但是CPU一直在不停的切换,给我们的假象就是他们同时在运行)————时间片

  • 多个进程在CPU上进行切换运行:(我们正在写vs上的++操作,但是时间片到了,切换到别的进程中,当下一次再切换回来时,++操作命令丢失,因为只有一个缓存区,为了解决这个问题,就引入了程序计数器,和上下文数据)

  • 交互式进程——和我们用户正在交互的进程

  • 批处理进程——在后台默默的进程(假设交互只有一个,批处理有一堆。导致交互了一下,然后卡好久处理批处理,所以引进优先级)

查看进程信息:

  • 根目录下有一个/proc,里面记录的就是进程运行的信息

  • ps -ef 查看所有的进程信息

  • ps aux 比上一个显示的更齐全

  • grep筛选信息

进程的创建:

pcb里内存指针指向内存的一块空间(程序数据,create程序),当需要一个新的进程时通过fork()函数创建一个子进程,他完全复制了父进程的所有信息。和父进程的程序计数器相同,下一步他们将运行相同的指令。那么如何区分父子进程?
  • pid_t fork(void);

    • pid_t 对于父进程返回的是子进程的pid
    • pid_t 对于子进程返回的是0
    • 父子进程返回值不同,父子进程公用同一个代码段,但是他们的数据并不公用

进程的状态:

  • 运行状态(running):意味着程序进程要么正在运行中,要么就在运行队列了。
  • 睡眠状态(sleeping):意味着可中断睡眠状态,等待事件完成
  • 磁盘睡眠状态(disk sleeping):不可中断睡眠(植物人)主要磁盘,是不可被中断的。
  • 停止状态(stopped):对比睡眠状态,睡眠状态只是正在睡眠,而停止状态是什么都不干
  • 追踪状态(tracing stop)
  • 死亡状态(dead):出现非常快
  • 僵尸状态(zombie)

僵尸进程:

  • 产生原因:子进程先于父进程退出,他要保留退出原因,在PCB中,因此退出后,不会释放所有资源,子进程退出后操作系统会通知父进程这个家属说子进程退出了,你去获取一下原因,然后完全释放资源。假如父进程不管子进程的退出状态,那么这个子进程将进入僵死状态,成为僵尸进程。

  • 危害:资源泄露

孤儿进程:

  • 产生原因:父进程先于子进程退出,那么这个子进程将会被成为孤儿进程,并进入后台运行

  • 解决方法:系统init进程变为父进程,也就是说子进程如果后来退出了,init进程将负责释放资源。init进程非常负责任,因此子进程不会成为僵尸进程。

优先级:

  • 为什么要有进程的优先级?

    多个进程同时进行中的进行,因为进程的功能各有不同,因此对CPU资源的要求也各有不同。因此对进程的调度,就有了优先级。优先级决定了CPU资源的优先分配权限。
  • PRI 优先级 默认80, 值越低,越优先。

  • NI nice值 设置进程优先级的参数

  • 进程的优先级:PRI+NI的值为优先级。

  • renice [-n] priority [[-p] pid …] [[-g] pgrp …] [[-u] user …]

  • 进程具有:竞争性、独立性、并行、并发

环境变量:

windows下面也有环境变量,点击我的电脑,管理,高级系统设置,环境变量。ls执行时,不需要添加路径,而执行某个文件前例如.c文件生成的test在执行前需要加./来告诉操作系统,而ls不需要添加的原因就是,linux操作系统的环境变量给ls路径。
  • 查看环境变量env

  • echo除了打印内容到屏幕上以外,还可以打印变量,前面加一个$来表明不是字符串

  • main函数第三个参数env

  • extern char ** environ

  • .c文件中可以用getenv获取环境变量的值。还有一个putenv

  • set也可以查看环境变量,unset,取消一个环境变量

cpu如何对进程进行调度切换

  • 进程就是pcb(task_struck)

  • task_struck中内存指针,程序计数器,上下文数据

  • pid_t vfork(void);

    • 这是一个基本淘汰的函数,功能与fork一样是创建一个子进程
  • 区别:

    • fork 是 创建一个子进程,并把父进程的内存数据复制到子进程中。
    • vfork是 创建一个子进程,并和父进程的内存数据分享一起用。
      • 特点:子进程没有(退出)或者运行其他程序则父进程是阻塞的,也就意味着子进程是先运行的。
      • 子进程先运行的原因:因为创建出子进程,大多时候都是为了让他运行其他程序
      • 父进程阻塞的原因:vfork创建子进程后,父子进程是共用一块虚拟地址空间那么他们共用同一个栈区,有可能会造成调用栈混乱。所以Vfork设计出来的目的就是为了创建一个子进程,然后直接运行其他的程序。重新运行其他程序就是重新给子进程开辟新的空间,更新他自己的一份地址空间和页表。自从fork函数使用了写时拷贝技术以后,这个函数就淘汰了。

进程终止:

  • 终止方式:

    • main函数中return则是退出进程

    • void exit(int status);

      • int status 进程退出状态
      • exit()库函数调用
      • 在程序任意位置调用都会使进程退出
      • main函数中return以后的,就会调用exit()
    • void _exit(int status);

      • void exit(int status);就是调用void _exit(int status);
      • _exit(int status)系统调用接口
    • exit与_exit的区别

      • exit是温和性的退出,在退出前会温和的释放资源
      • _exit是暴力退出,直接释放资源退出,不会刷新缓冲区
      • 也就是说调用exit函数以后,他先释放资源,然后调用_exit函数
    • 不管哪种主动退出方式,都会返回一个数字(包括return 0,都是输出完以后就调用_exit(0))这个数字是进程的退出状态,它表明了进程的退出原因。

    • 正常运行完毕主动退出,结果符合预期
    • 正常运行完毕,结果不符合预期
    • 异常退出,返回状态将不能作为评判标准。
    • 返回值只返回一个字节。所以最多255
    • 在main函数前加error,如果做系统调用,失败了,系统会自己给error一个值。这时候用strerror(error)可以将其打印出来。

进程的等待:

我们的进程退出之后,资源并非全部释放,我们有一个错误原因。保存在pcb中。所以为了保存错误原因,进程并不会完全退出,而是等待他的父进程来获取原因。假如父进程根本就没管,那么这个子进程就成了僵尸进程。危害就是资源泄露。因此为了防止出现僵尸进程,父进程就应该管一下子进程的退出。
  • pid_t wait(int *status);

父进程会专门关注(等待)子进程的状态。如果子进程退出,父进程会立马释放子进程资源。进程等待是避免为了产生僵尸进程的主要方式。
  • 这里的pid_t,就是说,一个父进程会有无数个子进程,他得知道是哪一个。pid_t就说获取退出的子进程的pid。status用于获取子进程 退出代码。返回值是返回退出的子进程pid。如果没有子进程,他会返回一个-1。显示的是报错。错误原因是调用进程根本没有子进程。他是一个阻塞性函数,就是说如果没有等到进程退出,他就挂起一直等待,直到等待到有子进程退出。
  • pid_t waitpid(pid_t pid, int *status, int options);

    • pid_t pid 如果给-1.就和wait一样等待任意子进程,如果大于0,就是专门等一个指定的子进程。
    • int *status 获取退出的状态码
    • int options 0是阻塞,WNOHANG是非阻塞,所以说waitpid是一个阻塞和非阻塞可选的等待进程。
    • 返回值:-1出错。0没有子进程退出,>0退出的的子进程pid。
    • 如果子进程延时退出,就得用while((id = waitpid(pid,NULL,WNOHANG))== 0)

进程的替换:

程序替换相当于让我们的虚拟地址空间中的代码段的地址指向了物理内存的另一端代码位置。这样的话,虚拟地址空间中,原先的数据区域以及堆栈都会重新初始化,因为现在的代码运行的根本不是复制的那些数据。
  • 但这个进程的PCB还是原来的PCB。

  • 一个程序main有三个参数,参数个数,参数的字符串指针,环境变量

  • exec函数族:exec并非函数,而是一个函数家族的名称

    • 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 execve(const char *filename, char *const argv[],char *const envp[]);
    • execl和execv的区别:l是参数平铺一个一个通过exec函数参数赋予,v参数直接使用字符串指针数组。
  • execl和execv 需要我们给出要替换程序的全路径名

  • execlp/execvp 只需要给出要替换的程序的名称就

  • execle 重新自己组织环境变量,不使用现有的。(就想说,父进程拥有自己的环境变量,创建出的子进程和父进程,本来一样,但是execle函数,就是说,他清空原有的环境变量。)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值