进程概念

  • 程序:存放在磁盘上的指令和有序的集合(文件)
    静态的

  • 进程
    执行一个程序所分配的资源的总称进程,是程序的一次执行过程
    动态的,包括创建、调度、执行和消亡

  • 代码段(txt):代码段通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

  • 数据端(data):常是指用来存放程序中已初始化的全局变量的一块内存区域。

  • BSS端(bss):常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started bySymbol的简称。

  • 堆(heap):堆是用于存放进程运行中被动态分配的内存段,当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)

  • 栈(stack):栈又称堆栈,是用户存放程序临时创建的局部变量上,(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进后出特点,所以栈特别方便用来保存1恢复调用现场。这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。进程控制块

  • 进程控制块(pcb)


    • 进程标识PID

    • 进程用户

    • 进程状态、优先级

    • 文件描述表
  • 进程的类型


    • 交互式进程:在shell下启动。以在前台运行,也可以在后台运行

    • 批处理进程:和在终端无关,被提交到一个作业队列中以便顺序执行

    • 守护进程:和终端无关,-直在后台运行

进程状态

  • 运行态:进程正在运行,或者准备运行
  • 等待态:进程在等待一个事件 的发生或某种系统资源
    可中断
    不可中断
  • 停止态:进程被中止,收到信号后可继续运行
  • 死亡志:已终止的进程,但pb没有被释放

命令

  • ps

  • ps -e //显示所有进程 -l //长格式显示更加详细的信息 -f//区别列出,通常和其他选项关联

  • ps -elf

  • top 查看进程动态信息 shiift +< 后翻页 shift+> 前翻页

  • top -p PID 查看某个进程

  • /proc 查看进程详细信息

  • renice 优先级 PID (改变进程优先级)

  • jobs 查看后台进程

  • bg 建挂起的进程在后台运行

  • fg 把后台运行的进程放到前台运行

  • ctrl+Z:将运行的前台进程转为后台并且停止运行

  • ./aout & 后台运行

子进程的概念

子进程为由另外一个进程(对应称为父进程的进程)所创建的进程称为子进程

子进程继承了父进程的内容
父子进程有独立的地址空间,互不影响
若父进程结束:
子进程称为孤儿进程,被init 进程收养
子进程变成后台进程

若子进程先结束
父进程还没有及时回收,子进程变成僵尸进程

练习:父进程->子进程->孙进程->重孙进程->曾孙进程

#include <stdio.h>
#include <unistd.h>

int main() {
  pid_t pid;
  int i = 0;
  for (i = 0; i < 4; i++) {
    pid = fork();
    if (pid < 0) {
      perror("fork");
      return 0;
    } else if (pid == 0) {
      printf("child process\n");
      sleep(5);
    } else {
      printf("Father process\n");
      sleep(5);
      break;
    }
  }
  sleep(100);
  return 0;
}

练习:一个父进程,5个子进程
#include <stdio.h>
#include <unistd.h>

int main() {
  pid_t pid;
  int i = 0;
  for (i = 0; i < 5; i++) {
    pid = fork();
    if (pid < 0) {
      perror("fork");
      return 0;
    } else if (pid == 0) {
      printf("child process\n");
      sleep(5);
      break;
    } else {
      printf("Father process\n");
      sleep(5);
      
    }
  }
  sleep(100);
  return 0;
}

进程的结束

#include < stdlib.h>
#include <unistd.h>
void exit(int status);
void_ exit(int status);
void_ Exit(int status);
➢结束当前的进程并将status返回
➢exit结束进程时会刷新(流)缓冲区

进程的回收

#include <sys/wait.h>
pid_ t wait(int *status);
成功时返回回收的子 进程的进程号;失败时返回EOF(-1)
若子进程没有结束,父进程直阻塞
若有多个子进程,哪个先结束就先回收
status指定保存子进程返回值和结束方式的地址
status为NULL表示直接释放子进程PCB,不接收返回值

练习:结束指定进程

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

int main() {
  pid_t pid;
  pid_t rpid;
  int status;
  pid = fork();
  if (pid < 0) {
    perror("fork");
    return 0;
  } else if (pid == 0) {
    sleep(1);
    printf("child process will exit\n");
    exit(2);
  } else if (pid > 0) {
    // rpid = wait(&status);//回收子进程
    rpid = waitpid(-1,&status,0);//和上面等价
    printf("Get Child status = %X\n", WEXITSTATUS(status) );//获取进程的返回值
  }
  while (1)
  {
   sleep(1);
  }
  

  return 0; // main函数:exit(0);
}