C语言进程(第一章进程基础,fork()函数,pid_t, pid, getpid())

女爷i 2024-03-22 13:10 150阅读 0赞

C语言进程(第一章进程基础,fork()函数,pid_t, pid, getpid())

简介

当我们用c编程构建一个应用时,常常会遇到这样的场景:需要在程序中同时完成几项任务,如处理数据、打印输出、和读取用户输入等。 这种需要同时进行多项任务效率更高的需求,就是“并发”。

一般由操作系统负责协调和分配计算机资源, 管理“进程”和“线程”。在c语言中,我们可以使用进程和线程来实现并发执行的目的。

  • 进程(process) 是操作系统管理资源,供程序运行时需要访问和控制的运行空间和内存地址。每个进程拥有自己的内存空间、系统资源、打开文件以及与其他进程的互动等等。

我们常把整个程序作为一个进程来处理,但是一个程序同时可能包含多个运行实例,即多个进程。 比如的浏览器中同时执行浏览网页、下载文件、播放视频等很多任务,那这些任务就会在不同的进程中执行。

入门

相关在线编辑网站:https://www.ideone.com/whPQYr

当学习进程和线程这些概念之后,下面是一些适合入门的C语言案例如下:

  1. 创建一个简单的进程

    include

    include

    include

    int main() {

    1. pid_t pid;
    2. pid = fork();
    3. if (pid == -1) {
    4. printf("error: 创建进程失败 \n");
    5. exit(1);
    6. } else if (pid == 0) {
    7. printf("我是子进程,我的pid是 %d \n", getpid());
    8. } else {
    9. printf("我是父进程,我的pid是 %d \n", getpid());
    10. }
    11. return 0;

    }

该程序使用fork()函数创建新进程。如果pid值小于0,则fork()系统调用失败并且创建一个新进程将无法完成;如果pid等于0,则说明当前运行的进程为子进程。所以我们执行该程序可以得到父进程的进程 id 和子进程的进程 id。

运行结果
在这里插入图片描述
运行结果解释:
这个程序运行的输出结果是:

  1. 我是父进程,我的pid 3173
  2. 我是子进程,我的pid 3213

在程序运行时,当 fork() 函数被调用时,进程会生成一个新的地址空间,然后把父进程的数据拷贝到新的地址空间中。新的进程就是所谓的子进程,它与父进程几乎完全相同,只有进程 ID 不同。

  • 在父进程中,fork()函数返回子进程的进程 ID 号,也就是变量 pid 值大于 0,如果pid等于-1,则说明进程创建失败。
  • 在子进程中,fork()函数返回0,因此在代码块 else if (pid == 0) 中执行,
    输出 “我是子进程,我的pid是 xxx” 的格式化字符串,使用 getpid() 来获取子进程的PID号码。
  • 在父进程中,在 else 语句块中执行,打印 “我是父进程,我的pid是 xxx”。使用 getpid() 来获取父进程自己的 PID 号。

两个打印信息出现的顺序是不确定的,这取决于操作系统选择在哪个进程上运行,这在每台计算机和每种操作系统都可能会有所不同。

fork()

fork()函数是Unix操作系统中创建新进程的一个函数。在C语言中,可以使用这个函数来创建新进程。

具体地说,当程序执行到 fork()函数时,它会创建一个子进程并使其运行同样的代码,相当于将原来的进程“复制”一份,形成了两个几乎完全相同的进程。其中,原有进程称为父进程,新创建出来的进程称为子进程。而在父进程和子进程中,通过fork()函数的返回值来区分不同进程,因为在子进程中,fork()函数将返回0,在父进程中,该值将是它所创建的子进程的进程ID。

fork() 函数可以用来实现普通进程的派生,也可以在后续中使用 execve() 系列函数去加载不同命令。

下面是基本的fork()函数使用案例:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. int main() {
  5. pid_t pid;
  6. pid = fork();
  7. if (pid == -1) {
  8. printf("error: 创建进程失败 \n");
  9. exit(1);
  10. } else if (pid == 0) {
  11. printf("我是子进程,我的pid是 %d \n", getpid());
  12. } else {
  13. printf("我是父进程,我的pid是 %d \n", getpid());
  14. }
  15. return 0;
  16. }

在这个例子里,调用fork()函数创建了一个子进程。如果fork()函数调用失败,那么就会返回-1;在子进程时,其返回值为0,而在父进程时其返回值是子进程 ID。

需要注意的是,fork()函数非常耗费资源,因为该函数需要拷贝整个进程。因此在代码中应当尽量避免使用超过必要的fork()函数调用,在多次使用时也需要减少系统资源消耗和时间延迟等方面进行优化。

运行结果:
在这里插入图片描述

pid

pid 是 “process ID” 的缩写,即进程ID。

在操作系统中,每个正在运行的进程都会被分配一个唯一的整数进程 ID (PID),用于标识该进程。进程 ID 在系统内部用作识别进程、管理进程状态等方面起着非常重要的作用,这意味着唯一的PID意味着对应唯一的进程标识符。在 Linux 和 Unix 系统中,可以使用 ps 命令和其他系统工具来查看当前运行的进程及其 PID。

你可以通过编写 shell 脚本 或 C 语言程序来获得当前进程的 pid,使用 getpid()函数,如下所示:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. int main() {
  5. printf("当前进程的pid是:%d\n", getpid());
  6. return 0;
  7. }

在该程序中,使用getpid()函数获取当前进程的 PID,并把其打印出来。因为每个进程的PID都是独特的,运行该程序时,您将会得到一个不同于其他正在运行进程的独特 PID 值输出结果。

总之,在操作系统中了解和使用进程 ID 很重要,这有助于开发人员和系统管理员进行多种监控和管理活动,以及进行更好的调试和错误处理。

运行结果
在这里插入图片描述

pid_t

在 C 语言中,pid_t 是一个整数类型,用于表示进程的 ID 。具体来说,在绝大多数 Unix 或 Linux 系统中,pid_t 的定义如下:

  1. typedef int pid_t;

因此,pid_t 实际上是 int 类型,而且在一般情况下其大小与 int 相等。

使用 pid_t 这种类型是为了能够让代码更加可移植。因为不同平台之间对于进程ID的实现可能会有所不同,比如 Windows 平台就使用 HANDLE 类型而非 pid_t;在32位系统和64位系统上PID最大值也可能不同,而使用这种类型可以保证程序在不同的平台上都能正常编译和运行。因此,在编写依赖于进程ID的程序时,最好使用 pid_t 而非硬编码整数类型。

在 C 标准库 <unistd.h>中,fork() 函数说明返回一个 pid_t 类型的值,从而方便地获得新创建进程的 PID 号,示例代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. int main() {
  5. pid_t pid;
  6. pid = fork();
  7. if (pid == -1) {
  8. printf("error: 创建进程失败 \n");
  9. exit(1);
  10. } else if (pid == 0) {
  11. printf("我是子进程,我的pid是 %d \n", getpid());
  12. } else {
  13. printf("我是父进程,我的pid是 %d \n", getpid());
  14. }
  15. return 0;
  16. }

在该程序中,定义 pid_t pid 来保存进程 ID 值,即 fork 函数返回值。这有助于让您的代码更符合 C 标准,并以可移植方式使用操作系统提供的功能。

发表评论

表情:
评论列表 (有 0 条评论,150人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Linux系统编程-进程(三):进程号、获取进程函数getpid():获取本进程号(PID)】【getppid():获取父进程号(PPID)】【getpgid():获取进程组号(PGID)】

    每个进程都由一个进程号来标识,其类型为 pid\_t(整型),进程号的范围:0~32767。 进程号总是唯一的,但进程号可以重用。 当一个进程终止后,其进程号就可以再次使用

    相关 进程之创建子进程fork,vfork函数

    本博文讲解的是关于进程的创建;首先我们要先知道什么是进程和进程的一些知识 > 1.进程:是一个正在运行时的程序,系统会给这个程序分配一些系统资源,例如:内存,管理文件的