Linux操作系统——进程介绍

本文深入解析了进程的概念,包括程序与进程的区别,进程的组成部分如文本段、用户数据段和系统数据段,以及如何在Linux系统中使用ps命令查看进程信息。此外,还探讨了进程的层次结构、状态转换及通过fork系统调用创建子进程的方法。

3.1进程介绍

1、程序和进程

程序是一个普通文件,是机器代码指令和数据的集合,这些指令和数据存储在磁盘上的一个可执行映像中。可以认为进程是运行中的程序,除了包含程序中的所有内容外,还包含一些额外的数据。进程代表程序的执行过程,是一个动态的实体,随着程序中指令的执行而不断地变化。在某个时刻进程的内容被称为进程映像。

进程是由文本段Text、用户数据段和系统数据段共同组成的一个执行环境。

(1)文本段:存放被执行的机器指令。这个段只读,允许系统中正在运行的两个或多个进程之间能够共享这一代码。

(2)用户数据段:存放进程在执行时直接进行操作的所有数据,包括进程使用的全局变量在内。这里包含的信息可以被改变。虽然进程之间可以共享文本段,但是每个进程需要有它自己的专用用户数据段。

(3)系统数据段:存放程序的运行环境。

在Linux系统中使用ps命令来查看当前系统中的进程和进程的一些相关信息。例如ps -e

2、进程的层次结构

在Linux中,通过调用fork系统调用创建一个新的进程。新创建的子进程也能执行fork,所以,有可能形成一棵完整的进程树。注意,每个进程只有一个父进程,但可以有0个、1个、2个或多个子进程。

init 进程是系统中唯一一个没有父进程的进程,它是系统中的第一个进程,其他进程都是由init进程或init进程的子进程产生的。

在Linux系统中用pstree命令来查看系统中进程的树状结构;也可用ps命令来显示进程的树状结构,例如ps -elH

3、进程状态

最基本的进程状态有如下三种:

1、运行态:进程占有CPU,并在CPU上运行。

2、就绪态:进程已经具备运行条件,但由于CPU忙而暂时不能运行。

3、阻塞态:进程因等待某种事件的发生而暂时不能运行(即使CPU空闲,进程也不可运行)。

进程在生命周期内处于且仅处于三种基本状态之一,这三种状态之间有以下4中可能的转换关系。

(1)运行态——>阻塞态:进程发现它不能运行下去时发生这种转换。这是因为进程发生IO请求或等待某件事情。

(2)运行态——>就绪态:在系统认为运行进程占用CPU的时间已经过长,决定让其他进程占用CPU时发生这种转换。由调度程序引起的。调度程序是操作系统的一部分,进程甚至感觉不到它的存在。

(3)就绪态——>运行态:运行进程已经用完分给它的CPU时间,调度程序从处于就绪态的进程中选择一个投入运行。

(4)阻塞态——>就绪态:当一个进程等待的一个外部事件发生时,发生这种转换。如果这时没有其他进程运行,则从就绪态转换为运行态,该进程便开始运行。

4、进程举例

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

void do_something(long t)
{
    int i = 0;

    for(i = 0; i < t; i++)
        for(i = 0; i < t; i++)
            for(i = 0; i < t; i++)
                ;
}


int main(void)
{
    pid_t pid;

    // 此时仅有一个进程
    printf("PID before fork(): %d\n", getpid());
    pid = fork();

    // 此时已经有两个进程在同时运行
    pid_t npid = getpid();
    if(pid < 0)
        perror("fork error\n");
    else if(pid == 0){ // 表示子进程
        while(1){
            printf("I am child process, PID is %d\n", npid);
            do_something(10000000);
        }
        
    }else if(pid > 0){ // 表示父进程
        while(1){
            printf("I am parent process, PID is %d\n", npid);
            do_something(10000000);
        }
    }


    return 0;
}

 

### 操作系统进程与线程的概念 #### 进程 (Process) 进程操作系统结构的基础,表示程序的一次执行过程。每个进程都有独立的代码和数据空间(指令、栈、堆),具有分配资源的功能单位。进程由文本区(即代码)、数据区以及用户堆栈组成,并且拥有自己的地址空间[^1]。 ```c // 创建新进程的例子 pid_t pid; pid = fork(); // Unix/Linux创建子进程的方式 if (pid < 0){ printf("error in fork!"); } else if(pid == 0){ printf("I am child process"); } else { wait(NULL); // 父进程等待子进程结束 } ``` #### 线程 (Thread) 线程有时被称为轻量级进程(Lightweight Process),同一进程内的多个线程共享该进程中大部分的数据和状态信息,如文件描述符、信号处理设置等;但是它们各自有自己的调用栈(call stack) 和寄存器集合(registers set)[^2]。 ```java class MyThread extends Thread{ public void run(){ System.out.println("This is a thread."); } } public class Main { public static void main(String[] args) { new MyThread().start(); } } ``` ### 进程与线程的主要区别 - **定义不同** - 进程是一个具有一定独立功能的程序关于某个数据集上的一次运行活动,而线程则是进程的一个实体,是CPU调度和分派的基本单位[^3]。 - **开销方面** - 启动一个新的进程所需的时间较长,因为这涉及到加载新的环境并初始化所有的上下文。相比之下,启动一个新线程则要快得多,因为它只需要复制父线程的一些属性即可完成创建工作[^4]。 - **资源共享** - 不同进程之间无法直接访问对方的内存区域,如果需要交换数据,则必须通过特定机制实现跨进程通讯(IPC) 。然而,在同一个进程下的各个线程间可以直接读写彼此所在的全局变量或静态方法中的局部变量,因此更容易进行协作工作。 - **通信方式** - 对于多进程而言,通常采用消息队列(message queue), 套接字(socket pair) 或者管道(pipe)等方式来进行相互通信;而对于属于同一进程的不同线程来说,由于它们都处于相同的地址空间内,故可通过共享存储器(shared memory segment)来高效传递信息。 - **调度粒度** - 在现代操作系统里,实际被调度的对象往往是线程而非整个进程——尽管后者确实包含了前者所需的全部资源和支持条件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值