专业建站服务建站网,阿图什网站,wordpress搭建教程,韩城搜索引擎建设网站下面是有关进程基础API的相关介绍#xff0c;希望对你有所帮助#xff01; 小海编程心语录-CSDN博客 目录
1. 僵尸进程与孤儿进程
1.1 孤儿进程
1.2 僵尸进程
2. 监视子进程
2.1 wait()
2.2 waitpid()
3. 执行新程序
exec族函数
4. 守护进程 1. 僵尸进程与孤儿进程… 下面是有关进程基础API的相关介绍希望对你有所帮助 小海编程心语录-CSDN博客 目录
1. 僵尸进程与孤儿进程
1.1 孤儿进程
1.2 僵尸进程
2. 监视子进程
2.1 wait()
2.2 waitpid()
3. 执行新程序
exec族函数
4. 守护进程 1. 僵尸进程与孤儿进程
1.1 孤儿进程 父进程先于子进程结束此时子进程变成了一个“孤儿”我们把这种进程就称为孤儿进程。 在 Linux 系统当中所有的孤儿进程都自动成为 init 进程的子进程 示例代码
#include stdio.h
#include stdlib.h
#include unistd.h
int main(void)
{// 创建子进程 switch (fork()){case -1:perror(fork error);exit(-1);case 0:// 子进程 printf(子进程%d被创建, 父进程%d\n, getpid(), getppid());sleep(3); // 休眠 3 秒钟等父进程结束printf(父进程%d\n, getppid()); // 再次获取父进程 pid_exit(0);default:// 父进程 break;}sleep(1); // 父进程休眠休眠 1 秒,保证子进程能够打印出第一个 printf()printf(父进程结束!\n);exit(0);
}
代码运行结果 1.2 僵尸进程 如果子进程先于父进程退出同时父进程太忙了无瑕回收子进程的内存资源那么此时子进程就变成了一个 僵尸进程僵尸一词指的是子进程结束后其父进程并没有来得及立马给它“收尸”子进程处于“曝尸荒野”的状态 回收进程有以下几种情况 如果父进程调用wait()为子进程收尸后僵尸进程就会被内核彻底删除。如果父进程并没有调用wait(函数然后就退出了那么此时init进程将会接管它的子进程并自动调用wait(),故而从系统中移除僵尸进程如果父进程创建了某一子进程子进程已经结束而父进程还在正常运行但父进程并未调用wait()回收子进程此时子进程变成一个僵尸进程 如果系统中存在大量的僵尸进程它们势必会填满内核进程表从而阻碍新进程的创建所以在我们的一个程序设计中一定要监视子进程的状态变化如果子进程终止了要调用wait()将其回收避免僵尸进程。 示例代码
#include stdio.h
#include stdlib.h
#include unistd.h
int main(void)
{// 创建子进程 switch (fork()){case -1:perror(fork error);exit(-1);case 0:// 子进程 printf(子进程%d父进程%d\n, getpid(), getppid());sleep(1); // 休眠 1秒钟printf(子进程结束!\n);_exit(0);default:// 父进程 break;}while(1)sleep(1);exit(0);
}代码运行结果 2. 监视子进程 在很多应用程序的设计中父进程需要知道子进程于何时被终止并且需要知道子进程的终止状态信息是正常终止、还是异常终止亦或者被信号终止等意味着父进程会对子进程进行监视同时还需要回收僵尸进程的资源 2.1 wait() 系统调用 wait() 可以等待进程的任一子进程终止同时获取子进程的终止状态信息 //函数原型
#include sys/types.h
#include sys/wait.h
pid_t wait(int *status);
函数参数和返回值含义如下 status参数 status 用于存放子进程终止时的状态信息参数 status 可以为 NULL表示不接收子进程 终止时的状态信息。 返回值若成功则返回终止的子进程对应的进程号失败则返回-1。 参数 status 不为 NULL 的情况下则 wait() 会将子进程的终止时的状态信息存储在它指向的 int 变量中可以通过以下宏来检查 status 参数 示例代码
#include sys/types.h
#include sys/wait.h
#include stdio.h
#include unistd.h
#include stdlib.h
#include errno.hint main()
{int status;pid_t pid;int i;int ret;for(i 1; i4; i){pid fork();switch(pid){case -1:perror(fork error);exit(-1);case 0:// 子进程 printf(子进程%d被创建\n, getpid());sleep(i); _exit(i);default:// 父进程 break;}}sleep(1);for(i 1; i4; i){ret wait(status);if(ret -1){if(ECHILD errno){printf(没有等待回收的进程\n);exit(0);}else{perror(wait error);exit(-1);}}printf(回收的子进程id: %d,回收状态%d\n, ret, WIFSIGNALED(status));}exit(0);
} 代码运行结果 2.2 waitpid() 使用 wait()系统调用存在着一些限制这些限制包括如下 如果父进程创建了多个子进程使用 wait()将无法等待某个特定的子进程的完成只能按照顺序等待下一个子进程的终止一个一个来、谁先终止就先处理谁。 如果子进程没有终止正在运行那么 wait() 总是保持阻塞有时我们希望执行非阻塞等待而waitpid()函数则可以突破这些限制。 //函数原型
#include sys/types.h
#include sys/wait.h
pid_t waitpid(pid_t pid, int *status, int options); status 与 wait()函数的 status 参数意义相同
返回值 返回值与 wait()函数的返回值意义基本相同
3. 执行新程序 当子进程的工作不再是运行父进程的代码段而是运行另一个新程序的代码那么这个时候子进程可以通过 exec 函数来实现运行另一个新的程序。 exec族函数 exec 族函数包括多个不同的函数这些函数命名都以 exec 为前缀这些库函数都是基于系统调用 execve() 而实现的虽然参数各异、但功能相同 包括 execl()、 execlp()、 execle()、 execv()、 execvp()、 execvpe() 示例代码
// child.c
#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/wait.h int main(int argc, char **argv)
{// 倒数 n 秒for(int iatoi(argv[1]); i0; i--){printf(%d\n, i);sleep(1);}// 程序退出返回 nexit(atoi(argv[1]));
}
// father.c
#include stdio.h
#include unistd.h
#include sys/wait.h int main()
{// 子进程if(fork() 0){printf(加载新程序之前的代码\n);// 加载新程序并传递参数3execl(./child, ./child, 3, NULL);printf(加载新程序之后的代码\n);}// 父进程else{// 等待子进程的退出int status;int ret waitpid(-1, status, 0);if(ret 0){if(WIFEXITED(status))printf([%d]: 子进程[%d]的退出值是:%d\n,getpid(), ret, WEXITSTATUS(status));}else{printf(暂无僵尸子进程\n);}}
}
代码运行结果 注意子进程中加载新程序之后的代码无法运行因为已经被覆盖了。 4. 守护进程 守护进程Daemon 也称为精灵进程是运行在后台的一种特殊进程它独立于控制终端并且周期性 地执行某种任务。 输入终端命令 ps -aux TTY 一栏是 表示该进程没有控制终端也就是守护进程其中 COMMAND 一栏使用中括号[]括 起来的表示内核线程这些线程是在内核里创建没有用户空间代码因此没有程序文件名和命令行通常 采用 k 开头的名字表示 Kernel 如果喜欢请不吝给予三连支持 小海编程心语录-CSDN博客