操作系统—进程(1)

一.进程的含义

进程是一个程序执行的过程,会去分配内存资源,cpu的调度。

pcb(process control block):进程控制块是一个结构体。

PID:进程标识符。

二.进程和程序的区别

程序:静态。存储在硬盘中代码,数据的集合。

进程:动态。程序执行的过程,包括进程的创建,调度,消亡。

.c------>a.out------>process(pid)

1)程序是永存的,进程是暂时的。

2)进程有程序状态的变化,程序没有。

3)进程可以并发,程序无并发。

4)进程与进程会存在竞争计算机的资源。

5)一个程序可以运行多次,变成多个进程;一个进程可以运行一个或多个程序。

6)内存分布:进程的空间是0~3G,内核的空间是3~4G

三.进程分类

1.交互式进程

与用户直接交互的进程。

2.批处理进程  shell脚本

执行一系列预定义任务的进程。

3.守护进程

在后台运行,为系统提供服务的进程。

四. 进程的作用

  • 进程的作用:实现资源的并发和并行使用。
  • 并发:多个进程在宏观上同时进行。
  • 并行:多个进程在微观上同时进行。

五. 进程的状态

  • 基本状态:就绪、执行、阻塞(等待、睡眠)。
  • Linux中的进程状态:运行、睡眠、僵尸、暂停。

六. 进程的调度和上下文切换

  • 进程调度是内核的主要功能之一。
  • 调度算法:时间片轮转(RR)、先进先出(FIFO)等。

七. 查询进程相关命令

  • ps aux:查看进程相关信息

        1.就绪态、运行态     R
        2.睡眠态、等待态    
           可唤醒等待态        S
           不可唤醒等待态    D
        3.停止态                   T
        4.僵尸态                   Z
        5.结束态    

  • top:根据CPU占用率查看进程信息

  • killkillall:发送信号给进程

    1.kill -2 PID  15
    发送信号+PID对应的进程,默认接收者关闭
    
    2.killall -9 进程名
    发送信号 进程名对应的所有进程
       killall a.out

八. 进程系统调用

1.pid_t fork();叉子

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

int main() {
    pid_t pid = fork();

    if (pid < 0) {
        // fork失败
        perror("fork failed");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        // 子进程
        printf("I am the child process, my PID is %d\n", getpid());
    } else {
        // 父进程
        printf("I am the parent process, my PID is %d, and the child PID is %d\n", getpid(), pid);
    }

    return 0;
}
  • 一次调用,两次返回fork() 在父进程中返回子进程的 PID,在子进程中返回 0。
  • 执行顺序不确定:子进程和父进程的执行顺序是不确定的,具体哪个先执行取决于操作系统的调度策略。
  • 变量不共享:在 fork() 调用时,子进程获得父进程数据空间的副本,但两个进程的变量是独立的,对一个进程中的变量所做的更改不会影响另一个进程。
  • 子进程复制:子进程复制父进程的用户空间(0到3GB),以及父进程的进程控制块(PCB),但两者拥有不同的 PID。
  • 功能fork() 用于克隆当前进程,创建一个同名的新进程,即子进程。子进程是父进程的完全拷贝,但它们是两个独立的进程,拥有自己的执行环境和资源。
返回值:
  • 父进程中:成功时返回子进程的 PID(一个大于 0 的整数),失败时返回 -1,并设置 errno 以指示错误。
  • 子进程中:成功时返回 0,失败时不会执行(因为子进程的创建失败,fork() 不会返回)。

2.pid_t getpid(void);

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

int main() {
    pid_t pid = getpid();  // 获取当前进程的 PID
    printf("Current process PID: %d\n", pid);
    return 0;
}
  • 原型pid_t getpid(void);
  • 功能: 获取调用该函数的进程的进程标识符(PID)。
  • 参数: 无(缺省)。
  • 返回值: 当前进程的 PID。

3.pid_t getppid(void);

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

int main() {
    pid_t parent_pid = getppid();  // 获取父进程的 PID
    printf("Parent process PID: %d\n", parent_pid);
    return 0;
}
  • 原型pid_t getppid(void);
  • 功能: 获取调用该函数的进程的父进程的 PID。
  • 参数: 无(缺省)。
  • 返回值: 调用进程的父进程的 PID。

4.fork() && fork() || fork();表达式分析

  • fork() && fork(): 首先调用 fork(),然后在父进程中根据第一次 fork() 的结果决定是否执行第二次 fork()。如果第一次 fork() 成功,会创建一个新的子进程,然后在父进程中执行第二次 fork(),可能再创建一个子进程。如果第一次 fork() 失败,整个表达式失败,不会执行第二次 fork()
  • fork() || fork(): 首先调用 fork(),如果失败,则执行第二个 fork()。如果第一个 fork() 成功,整个表达式成功,不会执行第二个 fork()

5.面试题解答

面试题解答

  1. 一次 fork() 生成几个进程?

    一次 fork() 调用生成两个进程:一个父进程和一个新的子进程。
  2. 他们之间的关系是什么样的?

    子进程是父进程的副本,拥有自己的 PID,但它继承了父进程的用户空间、打开的文件描述符、信号处理等。
  3. 如果两次 fork() 同时(或连续)执行,会生成几个进程?他们之间的关系如何表示?

    如果在父进程中连续执行两次 fork(),将生成三个进程:原始的父进程、第一个子进程和第二个子进程(孙进程)。他们可以表示为一个树状结构,原始父进程是树的根,第一个子进程是根的子节点,第二个子进程(孙进程)是第一个子进程的子节点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值