专业网站建设品牌策划,商务网站建设与维护考试,门户网站功能清单,想建网站须要什么条件进程替换和信号
问题引入 我们发现 终端输入的任意命令的父进程都是bash,这是因为Linux系统是用fork()复制出子进程#xff0c;然后在子进程中调用替换函数进行进程替换#xff0c;实现相关命令。
#xff08;1#xff09; exec 系列替换过程#xff1a;pcb 使用以前的只…进程替换和信号
问题引入 我们发现 终端输入的任意命令的父进程都是bash,这是因为Linux系统是用fork()复制出子进程然后在子进程中调用替换函数进行进程替换实现相关命令。
1 exec 系列替换过程pcb 使用以前的只修改进程实体更换。 进程替换函数 #include unistd.h int execl( const char * path, const char * arg,…); /* *path:新替换的程序的路径名称 *arg :传给新程序主函数的第一个参数一般为程序的名字 *arg 后面是剩余参数列表参数个数可变必须以空指针作为最后一个参数 */ int execlp( const char * file, const char * arg,…); /* int execlp( const char * file, const char * arg,…); /* *file:新替换的程序的名称 *arg :传给新程序主函数的第一个参数一般为程序的名字 *arg 后面是剩余参数列表参数个数可变必须以空指针作为最后一个参数 */ int execle( const char * path, const char * arg,…, char * const envp[]); /* *path:新替换的程序的路径名称 *arg :传给新程序主函数的第一个参数一般为程序的名字 *arg 后面是剩余参数列表参数个数可变必须以空指针作为最后一个参数 *const envp[] : 存放环境变量 */ int execv( const char * path, char * const argv[]); /* *path:新替换的程序的路径名称 const argv[] :存放命令参数的指针数组 */ int execvp( const char * file, char * const argv[]); /* *file: 新替换的程序的名称 const argv[] :存放命令参数的指针数组 */ int execve( const char * path, char * const argv[], char * const envp[]); /* *path:新替换的程序的路径名称 const argv[] :存放命令参数的指针数组 *const envp[] : 存放环境变量 */ 使用模板如下
#includestdio.h
#includestdlib.h
#includeassert.h
#includeunistd.h
#includestring.h
#include sys/wait.h
int main(int agrc,char*argv[],char*envp[]){printf(main pid%d \n,getpid() ); assert(pid!-1);if(pid0){printf(child pid%d,ppid%d\n,getpid(),getppid());//1. execl(/bin/ps,ps,-f,(char*)0);//2. execlp(ps,ps,-f,(char*)0);//3. execle(/usr/bin/ps,ps,-f,(char*)0,envp);char* myargv[]{ps,-f,0};//4. execv(/usr/bin/ps,myargv);//5. execvp(ps,myargv);//6. execve(/usr/bin/ps,myargv,envp); exit(0);} exit(0);
}Linux 信号的使用
信号是系统响应某个条件而产生的事件进程接收到信号会执行相应的操作。 与信号有关的系统调用在“signal.h”头文件中有声明 常见信号的值及对应的功能说明 信号的值在系统源码中的定义如下 #define SIGHUP 1#define SIGINT 2 //键盘按下 Ctrlc 时会产生该信号#define SIGQUIT 3#define SIGILL 4#define SIGTRAP 5#define SIGABRT 6#define SIGIOT 6#define SIGBUS 7#define SIGFPE 8#define SIGKILL 9 //该信号的响应方式不允许改变#define SIGUSR1 10#define SIGSEGV 11#define SIGUSR2 12#define SIGPIPE 13 //读端关闭的描述符写端写入时产生该信号会终止程序#define SIGALRM 14#define SIGTERM 15 //系统 kill 命令默认发送的信号#define SIGSTKFLT 16#define SIGCHLD 17 //子进程结束后会默认给父进程发送该信号#define SIGCONT 18#define SIGSTOP 19#define SIGTSTP 20#define SIGTTIN 21#define SIGTTOU 22#define SIGURG 23 修改信号的响应方式 – 调用signal() typedef void (*sighandler_t)(int); //函数指针类型重命名 **sighandler_t ** signal(int signum, sighandler_t sig_fun) /* signum : 处理的信号 sig_fun 处理信号的函数 1.SIG_IGN 忽略 2.SIG_DFL 默认 3.自定义自己写处理信号的函数 示例代码
#include stdio.h
#include unistd.h
#include stdlib.h
#include string.h
#include signal.h
void fun(int signum)
{printf(Call fun \n);
}int main()
{signal(SIGINT,fun);while(1){sleep(1);printf(Hello\n);}exit(0);
}
运行结果 发送信号 – kill()
kill() 可以向指定的进程发送指定的信号 int kill(pid_t pid, int sig); pid 0 指定将信号发送个那个进程 pid 0 信号被发送到和当前进程在同一个进程组的进程 pid -1 将信号发送给系统上有权限发送的所有的进程 pid -1 将信号发送给进程组 id 等于 pid 绝对值并且有权限发送的所有的进程。 sig 指定发送信号的类型。 示例代码
1.mykill.c
#include stdlib.h
#include stdio.h
#include string.h
#include signal.hint main(int argc,char* argv[])
{if(argc ! 3){printf(argc error\n);exit(1);}int pid atoi(argv[1]);int sig atoi(argv[2]);if(kill(pid,sig) -1){printf(kill error\n);}exit(0);
}
2.test1.c
#includestdio.h
#includestdlib.h
#includeassert.h
#includeunistd.h
#includestring.h
#includesignal.hvoid fun(int signum)
{printf(signum%d \n,signum);signal(SIGINT,SIG_DFL);
}int main()
{signal(SIGINT,fun);while(1){sleep(1);printf(Hello\n);}exit(0);
} 用信号处理fork()僵死进程
#includestdio.h
#includestdlib.h
#includeunistd.h
#includestring.h
#includesignal.h
#includesys/wait.h
void fun_sig(int sig)
{printf(end fork\n);wait(NULL);
}
int main()
{char*sNULL;int n0;signal(SIGCHLD,fun_sig);pid_t pidfork();if(pid-1){exit(1);}if(pid0){schild;n3;}else{sparent;n7;}int i0;for(;in;i){printf(s%s,pid%d\n,s,getpid());sleep(1);}exit(0);
}