什么是进程
从程序员角度看:执行程序的实体
从内核角度看:分配系统资源的基本单位(内存,堆栈等)
创建一个进程:
fork(),vfork():
#include<unistd.h>
pid_t fork(void);
pid_t vfork(void);
创建一个子进程,对其子进程返回0;父进程返回子进程 pid .
进程pid是内核对进程的唯一标识
fork()与vfork()的区别:
使用vfork()创建新的进程时,不将父进程的地址空间完全复制到子进程,而新进程的目的是 exec 一个新程序; vfork() 保证子进程先执行
注意:
- 使用 vfork() 时不应使用 exit();而应使用 _exit();
- 可移植的应用程序不应使用 vfork().
fork()出来的进程是父进程的进程映像,拥有与父进程相同的工作目录,屏蔽字,文件描述符等,而且文件指针都是指向相同的文件表,也就是说,他们打开的文件拥有相同的文件偏移量。
不同的是子进程不继承父进程的文件锁等,详细见《unix环境高级编程》8.3节。
tips:_exit()与exit()相比,退出时不执行标准IO清理,不调用终止处理程序。
atexit():
#include<stdlib.h>
int atexit(void (*func)(void));
返回值,成功->0;出错->非零
当调用exit()时自动调用由atexit()登记的函数,调用的顺序和登记时顺序相反。
wait():
#include<sys/wait.h>
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid,int *statloc,int option);
wait() 等待子进程终止,statloc 存放子进程终止状态;
waitpid中:
- pid=-1时等待任一子进程
- pid>0等待进程号为pid的子进程
- pid=0等待组id等于调用组id的任一子进程
- pid<-1等待组id为abs(pid)的任一子进程
测试statloc:
宏定义 描述
1. WIFEXITED(status) 如果子进程正常结束,返回一个非零值
2. WEXITSTATUS(status) 如果WIFEXITED非零,返回子进程退出码
3. WIFSIGNALED(status) 子进程因为捕获信号而终止,返回非零值
4. WTERMSIG(status) 如果WIFSIGNALED非零,返回信号代码
5. WIFSTOPPED(status) 如果子进程被暂停,返回一个非零值
6. WSTOPSIG(status) 如果WIFSTOPPED非零,返回一个信号代码
option参数:
- WCONTINUED:
- WNOHANG:不阻塞进程,若子进程没有终止立即返回0
- WUNTRACED:
函数 exec():fork()后执行新的程序
#include<unistd.h>
int execl(const char* path,const char* argv0,...);
int execv(const char* path,char * const argv[]);
int execle(const char* path,const char* argv0,...,char* const envp[]);
int execve
int execlp
int execvp
int fexecve
若出错返回-1,成功不返回
信号:
#inlcude<signal.h>
void (*signal(int sign,void (*func)(int)))(int)
void sigaction(int signo,const struct sigaction *restrict act ,struct sigaction *restricr oact);
相对于signal来说sigaction是信号安全的,所以这里不介绍signal大家自行查阅吧。
signo是要检测或修改其响应动作的信号编号,act要修改的动作,oact返回上一次的动作。
struct sigaction{
void (*sa_hander)(int);
sigset_t sa_mask;
int sa_flags;
void (*sa_sigaction)(int,siginfo_t,void *);
}
sa_mask是信号处理函数调用期间要阻塞的信号集
sa_flags:
SA_INTERRUPT
SA_NOCLDSTOP
SA_NOCLDWAIT
SA_NODEFER
SA_ONSTAT
SA_RESETHAND
SA_RESTART
SA_SIGINFO
#include<signal.h>
Sigfunc *signal(int signo,Sigfunc *func)
{
struct sigaction act,oact;
act.sa_hander=func;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
if(signo == SIGALRM){
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
}
else {
act.sa_flags |= SA_RESTART;
}
if(sigaction(signo,&act,&oact)<0)
return SIGERR;
return (oact.sa_hander);
}
哈哈,各位看官都猜出来了吧,这就是signal的一种实现。
sigsuspend():
#include<signal.h>
int sigsuspend(const sigset_t *sigmask);
返回值-1,并将errno设置为EINTR;
进程屏蔽字设置为sigmask,再捕捉到一个信号前,挂起进程,捕捉到信号返回,并恢复之前的信号屏蔽字。
暂存