泸州公司做网站,wordpress本地上传阿里元,wordpress评论表单,有哪些网站是可以接单做任务的文章目录 进程创建进程终止进程结果wait函数waitpid函数status参数 进程替换进程替换原理进程替换函数 补充/拓展 进程创建
fork函数
#include unistd.hpid_t fork(void);函数返回值#xff1a;
在父进程中#xff0c;fork函数返回子进程的进程ID#xff08;PIDunistd.hpid_t fork(void);函数返回值
在父进程中fork函数返回子进程的进程IDPID 在子进程中fork函数返回0。 fork执行失败时返回-1. fork 执行失败的原因一般是系统资源不足。
fork函数的一般使用逻辑:
int main() {pid_t pid fork();if (pid 0) {// fork失败创建子进程失败fprintf(stderr, Fork failed\n);return 1;} else if (pid 0) {// 子进程执行的代码逻辑printf(This is the child process\n);// 子进程执行其他任务...} else {// 父进程执行的代码逻辑printf(This is the parent process, child PID: %d\n, pid);// 父进程执行其他任务...}return 0;
}内核视角 分配新的内存块和内核数据结构给子进程 将父进程部分数据结构内容拷贝至子进程 添加子进程到系统进程列表当中 fork返回开始调度器调度
进程终止
进程终止的原因
main函数返回
return n**等同于执行exit(n**),因为调用main的运行时函数会将main的返回值当做 exit的参数。exit函数返回_exit函数返沪
#include unistd.hvoid _exit(int status);status 定义了进程的终止状态父进程通过wait来获取该值 虽然status是int但是仅有低8位可以被父进程所用。所以_exit(-1)时在终端执行$?发现返回值 是255。
信号终止
_exit函数和exit函数说明:
_exit函数
_exit函数是一个系统调用函数用于立即终止程序的执行不会执行任何清理工作包括关闭文件、释放内存等。
它的原型为void _exit(int status)。
status参数表示程序的终止状态通常0表示正常终止非零值表示异常终止。
_exit函数不会刷新缓冲区也不会调用任何终止处理程序直接退出程序。exit函数
exit函数是标准库函数用于终止程序的执行并执行一些清理工作如关闭文件、释放内存等。
它的原型为void exit(int status)。
status参数表示程序的终止状态通常0表示正常终止非零值表示异常终止。
exit函数会先刷新缓冲区然后调用终止处理程序通过atexit注册的函数最后退出程序。进程结果
获取进程结果的方法
命令获取 echo $$?是一个特殊变量用于获取上一个命令的退出状态码。退出状态码是一个整数值表示上一个命令的执行结果。
父进程进程调用函数等待
wait函数
#include sys/types.h
#include sys/wait.hpid_t wait(int *status);参数 status是一个指向整型变量的指针用于存储子进程的退出状态。 如果不关心子进程的退出状态可以将status设置为NULL。 返回值 wait()函数的返回值是子进程的进程ID如果出错则返回-1。 如果当前进程没有子进程返回-1并设置errno为ECHILD 如果调用被信号中断返回-1并设置errno为EINTR
waitpid函数
#include sys/types.h
#include sys/wait.hpid_t waitpid(pid_t pid, int *status, int options);参数 pid pid 0等待进程ID为pid的子进程。 pid -1等待任意子进程与wait函数相同。 pid 0等待与当前进程的进程组ID相同的任意子进程。
status 输入输出型参数一个指向整型的指针用于获取子进程的终止状态。
options WNOHANG: 若pid指定的子进程没有结束则waitpid()函数返回0不予以等待。 若正常结束则返回该子进程的ID。
返回值 如果成功等待到子进程的终止返回子进程的进程ID 如果指定的子进程尚未终止并且使用了WNOHANG选项则返回0 如果调用被信号中断返回-1并设置errno为EINTR 如果指定的子进程不存在或不属于当前进程的子进程组返回-1并设置errno为ECHILD
status参数
status不能简单的当作整形来看待可以当作位图来看待具体细节如下图只研究status低16比特 位可以看到只有先判断进程是正常退出后退出状态码才是有效的。
WIFEXITED 是一个宏macro用于检查 wait 或 waitpid 函数返回的子进程状态(status)是否是正常退出。WIFEXITED(status) 接受一个 status 参数该参数是 wait 或 waitpid 函数返回的子进程状态信息。WIFEXITED 宏会对 status 进行解析并返回一个非零值true表示子进程是正常退出的返回零值false表示子进程不是正常退出的。
如果 WIFEXITED(status) 返回为真可以使用 WEXITSTATUS(status) 宏来获取子进程的退出状态码。WEXITSTATUS(status) 会返回子进程的退出状态码该状态码通常是在子进程调用 exit 或返回 main 函数时传递的值。
如果 WIFEXITED(status) 返回为假可使用WTERMSIG(status)同样是通过wait或waitpid函数获取的子进程的终止状态。如果进程是由于收到信号而异常终止则WTERMSIG宏返回信号的编号否则返回0。
具体使用
#include stdio.h
#include sys/types.h
#include sys/wait.h
#include unistd.hint main()
{pid_t pid fork();if (pid 0) {// 子进程printf(This is child process\n);// 子进程正常退出退出状态码为 42exit(42);} else if (pid 0) {// 父进程int status;wait(status);if (WIFEXITED(status)) {// 子进程正常退出int exit_status WEXITSTATUS(status);printf(Child process exited with status: %d\n, exit_status);}else {// 子进程非正常退出WTERMSIG(int status); // WTERMSIG获取异常退出时信号的编号printf(Child process did not exit normally\n);}}else {// fork 出错perror(fork);return 1;}return 0;
}进程替换
进程替换原理
当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动 例程开始执行调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。结合下图进程替换的本质是替换虚拟内存和物理内存/外存的映射关系故这个过程保留了原进程的task_struct, 和原进程存储堆和栈区中的数据。
需要注意
进程替换后task_struct 结构体中执行流相关字段会被重置新的程序加载进来的代码从main函数重新开始执行环境变量存储在环境变量表中环境变量表也是task_struct的一个字段所以进行进程切换的用户可以通过调用不同类型的进程替换函数来决定是否保留环境变量进程替换本质没有创建新的task_struct, 也就是说没有创建新的进程故进程ID不变。堆、栈区数据被保留文件描述符存储在文件描述表中文件描述符表存储在task_struct中所以如果在进程替换前如果对文件描述符进行了重定向重定向的效果会保留到进程替换过后的进程里 。 进程替换函数
#include unistd.hint execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);返回值 成功无返回值 失败返回 -1 参数 path 可执行文件绝对路径 file 可执行文件名 arg 可变参数列表 envp 环境变量数组 argv 参数数组 记忆方法 l(list) : 表示参数采用列表 v(vector) : 参数用数组 p(path) : 有p自动搜索环境变量PATH e(env) : 表示自己维护环境变量
补充/拓展
终止信号 下图前31种信号为进程异常退出时可能接收的信号信号的具体含义可通过man手册查明。
man 7 signal核心转储 有时在本地运行程序时会报错Segmentation fault (core dumped) 这表明发生了核心转储。 Linux核心转储coredump是指在程序发生崩溃或异常终止时将程序在崩溃时的内存状态保存到磁盘上的一个文件中。这个文件可以用于调试程序找出导致程序崩溃的原因。 在Linux系统中当一个程序崩溃时默认情况下会生成一个核心转储文件。这个文件包含了程序崩溃时的内存映像、寄存器状态、堆栈信息等。通过分析这个文件开发人员可以确定程序崩溃的原因并进行调试。 要启用核心转储功能可以通过设置ulimit命令来控制。ulimit命令用于设置shell进程的资源限制其中包括核心转储文件的大小限制。可以使用ulimit -c命令来查看当前的核心转储文件大小限制使用ulimit -c unlimited命令来设置核心转储文件的大小为无限制。 当程序崩溃时核心转储文件会被保存在当前工作目录下。可以使用gdb调试器来分析核心转储文件。例如可以使用gdb程序名核心转储文件来加载核心转储文件并进行调试。 需要注意的是核心转储文件可能会非常大因此在生产环境中可能需要限制核心转储文件的大小以避免磁盘空间被耗尽。另外核心转储文件可能包含敏感信息因此在共享或提交给第三方时需要谨慎处理。 进程替换的实际使用位于代码调用cgi模式的部分 个人代码练习