目录
一、进程替换
二、Linux信号的使用
2.1 kill() 发送信号
2.2 signal() 改变进程对信号的响应方式
2.3 处理僵死进程
2.3.1 在信号处理函数中调用wait
2.3.2 Linux特有的
2.3.3 结果
linux上创造一个新进程,没有create创建方法,而是通过fork+exec系列,先将进程复制一份,将子进程替换成另外一个进程,这样就相当于创建一个进程
ps -f和bash没有任何关系,为什么ps -f的父进程是bash,因为bash将自己复制了一份,然后将ps -f替换了它的子进程,从而有了创造了该指令。
#include exec 系类方法介绍以 execl 为例:/**path:新替换的程序的路径名称*arg :传给新程序主函数的第一个参数,一般为程序的名字*arg 后面是剩余参数列表,参数个数可变,必须以空指针作为最后一个参数*/i nt 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[]);
#include
#include
#include
#include
#include
#include
int main(int agrc,char*argv[],char*envp[]){
printf("main pid=%d,ppid=%d\n",getpid(),getppid());
pid_t pid=fork();
assert(pid!=-1);
if(pid==0)
{
printf("child pid=%d,ppid=%d\n",getpid(),getppid());
char*myenvp[10]={"MYSTR=hello"};
execl("/bin/ps","ps","-f",(char*)0);
execlp("ps","ps","-f",(char*)0);
execle("/usr/bin/ps","ps","-f",(char*)0,myenvp);
char* myargv[]={"ps","-f",0};
execv("/usr/bin/ps",myargv);
execvp("ps",myargv);
execve("/usr/bin/ps",myargv,envp);
printf("execl error");
exit(0);
}
wait(NULL);
exit(0);
}
结果
信号的值在系统源码中的定义如下:1. #define SIGHUP 12. #define SIGINT 2 //键盘按下 Ctrl+c 时,会产生该信号3. #define SIGQUIT 34. #define SIGILL 45. #define SIGTRAP 56. #define SIGABRT 67. #define SIGIOT 68. #define SIGBUS 79. #define SIGFPE 810. #define SIGKILL 9 //该信号的响应方式不允许改变11. #define SIGUSR1 1012. #define SIGSEGV 1113. #define SIGUSR2 1214. #define SIGPIPE 13 //读端关闭的描述符,写端写入时产生,该信号会终止程序15. #define SIGALRM 1416. #define SIGTERM 15 //系统 kill 命令默认发送的信号17. #define SIGSTKFLT 1618. #define SIGCHLD 17 //子进程结束后,会默认给父进程发送该信号19. #define SIGCONT 1820. #define SIGSTOP 1921. #define SIGTSTP 2022. #define SIGTTIN 2123. #define SIGTTOU 2224. #define SIGURG 23
#include
#include
#include
#include
#include
#include
int main(int argc,char*argv[])
{
if(argc!=3)
{
printf("argc err\n");
exit(1);
}
int pid=atoi(argv[1]);
int sig=atoi(argv[2]);
if(kill(pid,sig)==-1)
{
printf("kill err\n");
}
exit(0);
}
#include
#include
#include
#include
#include
#include
void fun_sig(int sig){
printf("sig=%d",sig);
}
int main(){
signal(SIGINT,fun_sig);
while(1){
printf("main run\n");
sleep(1);
}
exit(0);
}
结果:
ctrl+c的信号值为2,与内核达成协议,当有ctrl+c时执行fun_sig()函数。
如果想要结束该进程 :
1.新建一个窗口,查看该进程编号,结束该进程
2.Ctrl +/
signal(SIGINT,SIG_IGN);忽略 ,如果再ctrl+c,系统不会终止,会继续执行
signal(SIGINT,SIG_DFL);默认,如果再ctrl+c,系统终止
signal(SIGINT,fun_sig);
#include
#include
#include
#include
#include
#include
void fun_sig(int sig){
printf("sig=%d\n",sig);
signal(sig,SIG_DFL);
}
int main(){
// signal(sig,SIG_DFL);//默认
// signal(sig,SIG_IGN);//忽略
signal(SIGINT,fun_sig);//自定义
while(1){
printf("main run\n");
sleep(1);
}
exit(0);
}
结果
当第一次使用ctrl+c时,调用自定义函数,返回该信号的值,第二次使用ctrl+c调用系统默认的,结束了该进程。
#include
#include
#include
#include
#include
#include
void fun_sig(int sig)
{
printf("sig=%d\n",sig);
wait(NULL);
}
int main()
{
char*s=NULL;
int n=0;
signal(SIGCHLD,fun_sig);
pid_t pid=fork();
if(pid==-1){
exit(1);
}
if(pid==0)
{
s="child";
n=3;
}
else
{
s="parent";
n=7;
}
int i=0;
for(;i
signal(SIGCHLD,SIG_IGN);
#include
#include
#include
#include
#include
#include
void fun_sig(int sig)
{
printf("sig=%d\n",sig);
wait(NULL);
}
int main()
{
char*s=NULL;
int n=0;
signal(SIGCHLD,SIG_IGN);
pid_t pid=fork();
if(pid==-1){
exit(1);
}
if(pid==0)
{
s="child";
n=3;
}
else
{
s="parent";
n=7;
}
int i=0;
for(;i