您的位置:首页 > 文旅 > 旅游 > 手机动画制作app免费_房产备案价格查询官网_竞价托管推广公司_免费聊天软件

手机动画制作app免费_房产备案价格查询官网_竞价托管推广公司_免费聊天软件

2025/5/13 6:02:48 来源:https://blog.csdn.net/2301_76903795/article/details/147089526  浏览:    关键词:手机动画制作app免费_房产备案价格查询官网_竞价托管推广公司_免费聊天软件
手机动画制作app免费_房产备案价格查询官网_竞价托管推广公司_免费聊天软件

一、概述

1.1 什么是进程?

在 Linux 系统中,进程是程序的一次动态执行过程。程序是静态的可执行文件,而进程是程序运行时的实例,系统会为其分配内存、CPU 时间片等资源。例如,输入 ls 命令时,系统创建进程执行 ls 程序来显示文件列表。进程是资源分配的基本单位,理解进程对掌握 Linux 系统运行机制至关重要。

1.2 查看进程

在 Linux 中,可使用 ps 命令查看系统中当前运行的进程。下面是一些常用的 ps 命令参数组合:

  • ps -ef
    • 功能:以全格式显示所有进程的详细信息。
    • 步骤
      1. 打开终端。
      1. 输入 ps -ef 并回车。
    • 示例输出
 
UID PID PPID C STIME TTY TIME CMDroot 1 0 0 00:00 ? 00:00:01 /sbin/init splashroot 2 0 0 00:00 ? 00:00:00 [kthreadd]

  • 参数解释
    • UID:进程所有者的用户 ID。
    • PID:进程的 ID 号。
    • PPID:父进程的 ID 号。
    • C:CPU 占用率。
    • STIME:进程启动时间。
    • TTY:进程关联的终端。
    • TIME:进程使用的 CPU 时间。
    • CMD:启动进程的命令。

在 Linux 中,除了 ps -ef,还可使用以下命令查看进程:​

  • ps aux:​
  • 功能:显示所有进程的详细资源使用情况(如内存、CPU 占用率)。​
  • 示例输出:​
TypeScript取消自动换行复制USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND ​root 1 0.0 0.1 24176 4360 ? Ss 00:00 0:01 /sbin/init splash ​

  • %CPU:CPU 占用百分比。​
  • %MEM:内存占用百分比。​
  • STAT:进程状态(如 S 表示睡眠,R 表示运行)。​
  • top 命令:​
  • 功能:动态实时显示进程资源占用情况,类似 Windows 任务管理器。​
  • 操作:输入 top 后,可按 q 退出。

二、进程的创建

2.1 fork 函数

在 C 语言里,fork 函数是创建新进程的关键函数。它的作用是复制当前进程,生成一个子进程,原进程则成为父进程。fork 函数的原型如下:

#include <unistd.h>pid_t fork(void);
  • 返回值
    • 在父进程中,fork 函数返回子进程的 PID(一个正整数)。
    • 在子进程中,fork 函数返回 0。
    • 若 fork 失败,返回 -1。
创建进程的步骤
  1. 包含必要的头文件:#include <unistd.h> 和 #include <stdio.h>。
  1. 调用 fork 函数创建子进程。
  1. 根据 fork 的返回值判断当前是父进程还是子进程,并执行相应的代码。
示例代码
#include <unistd.h>#include <stdio.h>int main() {pid_t pid;pid = fork();if (pid < 0) {perror("fork 失败");} else if (pid == 0) {// 子进程printf("我是子进程,我的 PID 是 %d,父进程的 PID 是 %d\n", getpid(), getppid());} else {// 父进程printf("我是父进程,我的 PID 是 %d,子进程的 PID 是 %d\n", getpid(), pid);}return 0;}
编译和运行步骤
  1. 把上述代码保存为 fork_example.c。
  1. 打开终端,进入代码所在目录。
  1. 使用 gcc 编译代码:gcc fork_example.c -o fork_example。
  1. 运行编译后的可执行文件:./fork_example。

三、僵尸进程

3.1 形成条件

僵尸进程的形成需要满足以下三个条件:

  1. 子进程优先于父进程结束。
  1. 父进程不结束。
  1. 父进程不调用 wait 函数。

当子进程结束时,它会向父进程发送一个 SIGCHLD 信号,但如果父进程没有调用 wait 或 waitpid 函数来回收子进程的资源,子进程就会变成僵尸进程。

3.2 如何避免僵尸进程

方法一:父进程调用 wait 函数

wait 函数的作用是等待任意一个子进程结束,并回收其资源。其原型如下:

#include <sys/types.h>#include <sys/wait.h>pid_t wait(int *status);
  • 参数:status 用于存储子进程的退出状态。
  • 返回值:返回结束的子进程的 PID。
示例代码
#include <unistd.h>#include <stdio.h>#include <sys/types.h>#include <sys/wait.h>int main() {pid_t pid;pid = fork();if (pid < 0) {perror("fork 失败");} else if (pid == 0) {// 子进程printf("子进程开始执行,PID 是 %d\n", getpid());sleep(2);printf("子进程结束\n");} else {// 父进程int status;pid_t child_pid = wait(&status);printf("父进程回收了 PID 为 %d 的子进程\n", child_pid);}return 0;}
方法二:使用 signal 函数处理 SIGCHLD 信号

可通过 signal 函数捕获 SIGCHLD 信号,并在信号处理函数中调用 wait 或 waitpid 函数。

示例代码
#include <unistd.h>#include <stdio.h>#include <sys/types.h>#include <sys/wait.h>#include <signal.h>void sigchld_handler(int signo) {pid_t pid;int status;while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {printf("回收了 PID 为 %d 的子进程\n", pid);}}int main() {signal(SIGCHLD, sigchld_handler);pid_t pid;pid = fork();if (pid < 0) {perror("fork 失败");} else if (pid == 0) {// 子进程printf("子进程开始执行,PID 是 %d\n", getpid());sleep(2);printf("子进程结束\n");} else {// 父进程printf("父进程继续执行\n");sleep(5);}return 0;}

四、孤儿进程

4.1 形成条件

孤儿进程的形成需要满足以下两个条件:

  1. 父进程优先于子进程结束。
  1. 子进程未结束。

当父进程结束后,子进程就会变成孤儿进程,此时它会被进程 ID 为 1 的 init 进程接管。

4.2 被进程 ID 为 1 的进程接管

init 进程会负责回收孤儿进程的资源,确保系统资源不会被浪费。

示例代码
#include <unistd.h>#include <stdio.h>int main() {pid_t pid;pid = fork();if (pid < 0) {perror("fork 失败");} else if (pid == 0) {// 子进程printf("子进程开始执行,父进程 PID 是 %d\n", getppid());sleep(5);printf("子进程继续执行,父进程 PID 是 %d\n", getppid());} else {// 父进程printf("父进程结束\n");}return 0;}

在这个示例中,父进程会先结束,子进程在睡眠 5 秒后,会发现自己的父进程 ID 变成了 1。

五、守护进程(后台进程)

5.1 实现过程

守护进程是一种在后台持续运行的进程,通常在系统启动时就开始运行,并且不受用户登录和注销的影响。以下是创建守护进程的详细步骤:

步骤 1:创建子进程,父进程退出
#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main() {pid_t pid;pid = fork();if (pid < 0) {perror("fork 失败");exit(EXIT_FAILURE);}if (pid > 0) {// 父进程退出exit(EXIT_SUCCESS);}// 子进程继续执行// 后续步骤...return 0;}
步骤 2:在子进程中创建新会话
#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>int main() {pid_t pid;pid = fork();if (pid < 0) {perror("fork 失败");exit(EXIT_FAILURE);}if (pid > 0) {// 父进程退出exit(EXIT_SUCCESS);}// 子进程创建新会话pid_t sid = setsid();if (sid < 0) {perror("setsid 失败");exit(EXIT_FAILURE);}// 后续步骤...return 0;}

setsid 函数的作用是创建一个新的会话,使子进程成为新会话的首进程,并且脱离原有的控制终端。

步骤 3:改变工作目录
#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>int main() {pid_t pid;pid = fork();if (pid < 0) {perror("fork 失败");exit(EXIT_FAILURE);}if (pid > 0) {// 父进程退出exit(EXIT_SUCCESS);}// 子进程创建新会话pid_t sid = setsid();if (sid < 0) {perror("setsid 失败");exit(EXIT_FAILURE);}// 改变工作目录if (chdir("/") < 0) {perror("chdir 失败");exit(EXIT_FAILURE);}// 后续步骤...return 0;}

chdir 函数用于将工作目录切换到根目录,避免工作目录被卸载导致进程无法正常工作。

步骤 4:设置文件权限掩码
#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>int main() {pid_t pid;pid = fork();if (pid < 0) {perror("fork 失败");exit(EXIT_FAILURE);}if (pid > 0) {// 父进程退出exit(EXIT_SUCCESS);}// 子进程创建新会话pid_t sid = setsid();if (sid < 0) {perror("setsid 失败");exit(EXIT_FAILURE);}// 改变工作目录if (chdir("/") < 0) {perror("chdir 失败");exit(EXIT_FAILURE);}// 设置文件权限掩码umask(0);// 后续步骤...return 0;}

umask 函数用于设置文件权限掩码,确保守护进程创建的文件具有预期的权限。

步骤 5:关闭不需要的文件描述符
#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>int main() {pid_t pid;pid = fork();if (pid < 0) {perror("fork 失败");exit(EXIT_FAILURE);}if (pid > 0) {// 父进程退出exit(EXIT_SUCCESS);}// 子进程创建新会话pid_t sid = setsid();if (sid < 0) {perror("setsid 失败");exit(EXIT_FAILURE);}// 改变工作目录if (chdir("/") < 0) {perror("chdir 失败");exit(EXIT_FAILURE);}// 设置文件权限掩码umask(0);// 关闭不需要的文件描述符close(STDIN_FILENO);close(STDOUT_FILENO);close(STDERR_FILENO);// 守护进程的主循环while (1) {// 执行守护进程的任务sleep(1);}return 0;}

关闭标准输入、标准输出和标准错误输出的文件描述符,防止守护进程与控制终端交互。

编译和运行步骤

  1. 把上述代码保存为 daemon_example.c。
  1. 打开终端,进入代码所在目录。
  1. 使用 gcc 编译代码:gcc daemon_example.c -o daemon_example。
  1. 运行编译后的可执行文件:./daemon_example。此时,守护进程会在后台持续运行。

通过以上步骤,你可以逐步掌握 Linux 多进程的相关知识,包括进程的创建、僵尸进程和孤儿进程的处理,以及守护进程的实现。在实际应用中,多进程编程可以提高程序的并发性能,充分利用多核 CPU 的资源。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com