进程基本介绍
来源:互联网 发布:淘宝开店得多少钱2016 编辑:程序博客网 时间:2024/06/07 15:13
1、进程创建
pid_t fork();
fork
返回的值非常有趣。其中一个返回 0;另一个返回一个非零值。获得 0 的进程称为子进程,非零结果属于原始进程,即父进程.
int main(){ pid_t pid; pid = fork(); printf("mypid = %d, my paraent pid = %d, call pid = %d \n", getpid(), getppid(), pid); exit(0);}
执行结果
mypid = 888982, my paraent pid = 1409130, call pid = 553050
mypid = 553050, my paraent pid = 888982, call pid = 0
看到fork创建一个新的进程553050,返回值pid为0,父进程888982,返回值为子进程ID,fork调用一次,返回两次。
2、僵死进程
当子进程比父进程提前退出,但是没有告诉父进程退出情况,导致子进程不会被内核回收,而一直存在进程表空间。需要等父进程退出后,内核最终能够回收未确认的子进程以及父进程,这意味着可消除僵死进程的唯一方法是终止父进程。但是如何防止出现僵死进程呢?先看代码,后面再说
int main(){ pid_t pid; pid = fork(); if (pid == 0) { printf("mypid = %d, my paraent pid = %d, call pid = %d \n", getpid(), getppid(), pid); exit(0); } sleep(60); printf("mypid = %d, my paraent pid = %d, call pid = %d \n", getpid(), getppid(), pid); exit(0);}
1515654 Z 0:00 <defunct>
1392728 0.0 0.0 148 380 pts/36 A 10时39分59秒 0:00 ./fort_t
查看进程表,发现子进程实效(defunct),但是进程ID还存在,这就是僵死进程了。
如何避免僵死进程呢?
使用信号机制,当子进程终止时,会使用一个名为 SIGCHLD
的信号来通知其父进程。看代码
#include <unistd.h>#include <sys/wait.h>#include <sys/types.h>void sighander(int sig){ printf("hander sig is %d\n", sig); wait(0);} int main(){ pid_t pid; pid = fork(); sigset(SIGCHLD, &sighander); if (pid == 0) { printf("mypid = %d, my paraent pid = %d, call pid = %d \n", getpid(), getppid(), pid); exit(0); } sleep(60); printf("mypid = %d, my paraent pid = %d, call pid = %d \n", getpid(), getppid(), pid); exit(0);}
由于使用了 sigset
函数(它向信号处理程序分配一个函数指针)。每当进程接收到某个已处理的信号时,就会调用通过 sigset
分配的函数。对于 SIGCHLD
信号,应用程序必须调用wait()
函数,以等待子进程退出。由于该进程已经退出,这相当于向内核确认了子进程的终止。实际上,父进程所做的工作可能不只是确认该信息。它还可能需要清理子进程的数据。
3、wait
pid_t wait(int *statloc); //函数若成功,返回进程ID,若出错则返回-1;
如果一个进程结束了,不论是正常的还是非正常的,内核都会通过发送SIGCHLD 信号给父进程。子进程的结束是个异步事件,父进程执行这个信号,通过内核的异步通知,父进程可以选择忽略该信号,或者提供一个该信号发生时即被调用执行的函数。对于这种信号的系统默认动作是忽略它。
父进程通过调用wait 和waitpid,有如下调用情况
① :如果所有的子进程正在运行,父进程阻塞。
②:如果一个子进程结束了,父进程通过wait 取得了结束进程的状态值,父进程会立即随着子进程的结束状态返回。
③:如果进程没有子进程那么返回error 。
#include <unistd.h>#include <sys/wait.h>#include <sys/types.h>#include <sys/errno.h>#include <vector.h>#define MAX_SIZE 5void sighander(int sig){ printf("hander sig is %d\n", sig); wait(0);}int main(){ pid_t pid; vector<pid_t> vSubPid; //sigset(SIGCHLD, &sighander); for (int i = 0; i < MAX_SIZE; ++i) { pid = fork(); if (pid == 0) { printf("mypid = %d, my paraent pid = %d, call pid = %d \n", getpid(), getppid(), pid); exit(i); } else { vSubPid.push_back(pid); } } int status = 0; int num = 0; pid_t wait_pid; while (num < vSubPid.size()) { wait_pid = wait(&status); if (wait_pid == -1) { printf("wait error, no(%d), %s\n", errno, strerror(errno)); return -1; } if (WIFEXITED(status)) { if(WEXITSTATUS(status) < 0) { printf("SubProcess(%d) return err value=%#x\n", wait_pid, WEXITSTATUS(status)); return -1; }else { printf("SubProcess(%d) return value=%#x \n", wait_pid, WEXITSTATUS(status)); } } num++; } printf("mypid = %d, my paraent pid = %d, call pid = %d \n", getpid(), getppid(), pid); exit(0);}
执行结果
这个例子主要是用了宏WIFEXITED()和WEXITSTATUS来对子进程的状态进行控制
WIFEXITED(status) 这个宏用来指出子进程是否为正常退出的,如果是,它会返回一个非零值。
WEXITSTATUS(status) 当WIFEXITED返回非零值时,我们可以用这个宏来提取子进程的返回值,如果子进程调用exit(5)退出,WEXITSTATUS(status) 就会返回5;如果子进程调用exit(7),WEXITSTATUS(status)就会返回7。请注意,如果进程不是正常退出的,也就是说, WIFEXITED返回0,这个值就毫无意义。
4、Waitpid函数
- pit_t wait(pid_t pid,int *status,int options);
当我们需要等待一个特定进程的函数时候,我们这个时候需要用到了waitpid函数了。从上文看到waitpid函数原型,我们也都了解到有个pid_t参数。
解释如下:
Pid=-1,等待任一个子进程,与wait等效。
Pid>0.等待其进程ID与pid相等的子进程。
Pid==0等待其组ID等于调用进程组ID的任一个子进程。
Pid<-1等待其组ID等于pid绝对值的任一子进程
这个就不举例子了,大家可以自己试试。
- 进程基本介绍
- 僵尸进程的基本介绍
- nodejs学习--子进程 child_process模块的基本介绍
- 基本进程解析
- 基本系统进程
- 进程的基本属性
- vista的基本进程
- 进程基本结构说明
- 进程基本结构说明
- XP系统基本进程
- 进程的基本状态
- 进程的基本操作
- 基本的系统进程
- Linux进程基本操作
- 进程编程基本函数
- 进程的基本状态
- 进程的基本控制
- Fresco基本使用基本介绍
- C++代码优化
- Pat(Basic Level)Practice--1011(A+B和C)
- 黑马程序员--C#中的引用类型和值类型传递总结
- 带标签的viewpager自动切换+滑动切换+点击标签切换 带动画效果
- 个人Qt 学习记录 --- 自义定QPushButton
- 进程基本介绍
- ACCESS中如何比较日期和时间,使用DateDiff函数
- BeagleBoard Black run Ubuntu System
- jdbc2
- PlayMaker 相关
- 4. linux中强大的screen命令
- 关于UILabel自适应位置和高度大小的问题
- c语言与预处理指令
- 物联网