001- 什么是进程

1 - 进程

程序:计算机指令集合,一组静态的指令集,比如写的微信小程序的代码、记事本.exe等

程序在自己地址空间的一次活动,就是进程,更多细节 查看 进程详解

进程简单举例
  • 进程: 拥有独立地址空间, 是程序在自己的地址空间的一次执行活动。 比如打开一次记事本,就是一个进程
    • 主要目的 :操作系统都是多任务的,一个进程如果失败,最好不要影响其他进程,提高操作系统的强壮性
  • 下图 就是 我打开两次记事本,window进程中就会发现存在两个进程,进程pid不相同
    在这里插入图片描述
进程控制块(PCB)
  • 在linux中,PCB就是 task_struct结构体 ,pcb是进程的唯一标识
  • 在进程创建时,为该进程生成一个pcb , 进程终止时,回收pcb
  • pdb 包含 进程状态 state、进程标识信息(uid,gid)、定时器、用户可见寄存器,控制器,栈指针
  • 每个进程都有唯一进程id (pid)
  • 进程的状态转换,如下

在这里插入图片描述

进程的创建
  • 新进程的创建
    • 首先在内存中为新进程创建一个task_struct结构,
    • 然后 将父进程的task_struct内容复制其中
    • 再修改部分数据,分配新的内核堆栈,新的pid,
    • 再将task_struct这个node添加到链表中
  • 子进程刚开始,内核并没有为他分配物理内存,而是以只读的方式共享父进程内存
    • 只有子进程写时,才复制 ,即 copy-on-write
fork函数
  • fork 翻译过来,即时派生,分支等意思
  • fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,
    • 也就是两个进程可以做完全相同的事,
    • 但如果初始参数或者传入的变量不同,两个进程也可以做不同的事
  • 如果成功调用,则返回值
    • 父进程,调用,返回子进程的pid
    • 子进程,调用,返回0
  • 一般来说,fork之后,父子进程的执行顺序器不确定,看内核调度算法
  • 什么时候fork
    • 一个父进程,希望子进程同时执行不同代码
  • vfork 和fork的不同是, fork是复制一份父进程的内存空间、堆和栈, vfork是共享内存数据
    • vfork用时,一般都是紧接着调用exec,所以不会访问父进程数据空间
  • 注意 : 结束子进程的调用是exit()而不是return
    • return 会把父进程的 栈空间给返回了,导致不可预知错误 (与内核有关)
进程终止
  • 正常终止
    • 从main返回、等效调用exit
    • 调用exit
    • exit首先调用各终止处理程序,然后按需多次调用fclose,关闭各个流
    • 最后一个线程从启动例程返回
    • 最后一个线程调用pthread_exit
  • 异常终止
    • 调用abort
    • 接到一个信号并终止
    • 最后一个线程对取消请求做相应
wait和waitpid
  • wait用于是父进程阻塞,等待子进程退出
  • waitpid有若干选项,比如可以提供一个非阻塞的wait,也能实现和wait相同功能(linux中wait就是这样实现的)
  • 下图运行过程,见代码
#include<stdio.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
 pid_t child1,child2,child;
 if((child1 = fork()) < 0){
 perror("failed in fork 1");
 exit(1);
 }
 if((child2 = fork()) < 0){
 perror("failed in fork 2");
 exit(1);
 }
 if(child1 == 0){
 //run ls -l
 if(child2 == 0){
 printf("in grandson\n");
 }
 else if(execlp("ls", "ls", "-l", NULL) < 0){
 perror("child1 execlp");
 }
 }
 else if(child2 == 0){
 sleep(5);
 exit(0);
 }
 else{
 do{
 sleep(1);
 printf("child2 not exits\n");
 child = waitpid(child2, NULL, WNOHANG);
 }while(child == 0);
 if(child == child2){
 printf("get child2\n");
 }
 else{
 printf("Error occured\n");
 }
 }
}

在这里插入图片描述

后台进程
  • 守护进程 daemon , 是linux的后台服务进程,是一个生存周期较长的进程,没有控制终端

  • 守护进程创建步骤:

    1、创建子进程,父进程退出,子进程被init自动收养;fork exit

    2、调用setsid创建新会话,成为新会话的首进程,成为新进程组的组长进程,摆脱父进程继承过来的会话、进程组等;setsid

    3、改变当前目录为根目录,保证工作的文件目录不被删除;chdir(“/”)

    4、重设文件权限掩码,给子进程更大的权限;umask(0)

    5、关闭不用的文件描述符,因为会消耗资源;clos

僵尸进程
  • 在进程调用了exit之后,该进程并非马上就消失掉,而是留下了一个成为僵尸进程的数据结构,记载该进程的退出状态等信息供其他进程收集,除此之外,僵尸进程不再占有任何内存空间
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值