嵌入式Linux系统编程 — 7.1 深入理解进程

发布于:2024-07-05 ⋅ 阅读:(18) ⋅ 点赞:(0)

目录

1 理解线程与进程

1.1 线程与进程

1.2 并发与并行

2 进程与程序

2.1 程序如何开始?

2.2 程序如何结束?

3 进程号 


1 理解线程与进程

1.1 线程与进程

进程:进程是操作系统进行资源分配和调度的一个独立单位,每个进程都有自己的独立内存空间,至少有一个线程,即主线程。进程可以理解为完成一件事的完整解决方案,而线程可以理解为这个解决方案中的的一个步骤,可能这个解决方案就这只有一个步骤,也可能这个解决方案有多个步骤。

线程:线程是进程中的一个执行流,是CPU调度和分派的基本单位,它被包含在进程之中,进程包含一个或者多个线程。

1.2 并发与并行

并发:是指两个或多个事件在同一时间间隔发生,并发是针对单核 CPU 提出的,在同一CPU上的多个事件。

并行:是指两个或者多个事件在同一时刻发生,并行则是针对多核 CPU 提出,在不同CPU上的多个事件

2 进程与程序

2.1 程序如何开始?

在Linux系统中,程序的main()函数是由操作系统的程序加载器调用的。当用户通过命令行或其他方式启动一个C程序时,操作系统会加载程序的可执行文件到内存中,并初始化程序的执行环境,包括设置堆栈、分配内存等。随后,加载器会定位到程序的入口点,也就是main()函数,并将其传递给CPU开始执行。

main()函数的调用过程与进程的生命周期紧密相关。在Linux中,每个运行的程序都是一个或多个进程,当main()函数开始执行时,它实际上是在进程的上下文中运行的,进程是操作系统分配资源和调度任务的基本单位。

2.2 程序如何结束?

程序结束其实就是进程终止,进程终止的方式通常有多种,大体上分为正常终止和异常终止, 正常终止包括:

  • main()函数中通过 return 语句返回来终止进程;
  • 应用程序中调用 exit()函数终止进程;
  • 应用程序中调用_exit()或_Exit()终止进程;
  • 应用程序中调用 abort()函数终止进程;
  • 进程接收到一个信号,譬如 SIGKILL 信号。

atexit()库函数用于注册一个进程在正常终止时要调用的函数,其函数原型如下所示:

#include <stdlib.h>

int atexit(void (*function)(void));
  • function: 函数指针,指向注册的函数,此函数无需传入参数、无返回值。
  • 返回值: 成功返回 0;失败返回非 0。

下面的程序是atexit()库函数的调用实例:

#include <stdio.h>
#include <stdlib.h>

// 注册的退出函数,将在程序退出时调用
static void bye(void)
{
    puts("Goodbye!");
}

int main(int argc, char *argv[])
{
    // 使用atexit注册退出时调用的函数
    // 如果注册失败,将打印错误信息并以非零状态退出
    if (atexit(bye) != 0) {
        fprintf(stderr, "cannot set exit function\n");
        exit(-1);
    }

    exit(0);
}

atexit函数被用来注册bye函数,这样当程序退出时,bye函数会被自动调用。如果atexit调用失败,程序将打印错误信息并通过exit(-1)状态退出。如果atexit调用成功,程序将正常执行,最后以通过exit(0)状态退出,此时bye函数会被自动调用。

3 进程号 

进程号(PID)是操作系统分配给每个运行中的程序的唯一标识符,它允许系统和用户识别和管理不同的进程,确保每个进程都能独立地运行并访问系统资源。

在 Ubuntu 系统下执行 ps 命令可以查到系统中进程相关的一些信息,包括每个进程的进程号,如下所示:

上图中红框标识显示的是每个进程所对应的进程号,在某些系统调用中,进程号可以作为传入参数、有时也可作为返回值。譬如系统调用 kill()允许调用者通过进程号向某一个进程发送一个信号。

在应用程序中,可通过系统调用 getpid()来获取本进程的进程号,其函数原型如下所示:

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

pid_t getpid(void);

使用 getpid()函数获取进程的进程号:

#include <stdio.h>  // 包含标准输入输出库
#include <sys/types.h>
#include <unistd.h>


// 定义main函数,程序的入口点
int main() 
{
    // 使用getpid()获取当前进程的进程号
    pid_t pid = getpid();

    // 打印进程号
    printf("The process ID is: %d\n", pid);

    // 程序正常退出
    return 0;
}

使用getpid()函数获取当前进程的进程号,并将其存储在pid_t类型的变量pid中。pid_t是一个通常用于存储进程ID的类型,它的定义依赖于具体的系统和编译器。 


网站公告

今日签到

点亮在社区的每一天
去签到