exec:执行指定程序的函数族
目的:fork创建进程之后,子进程和父进程执行相同的代码,但是在实际开发当中,我们希望父子进程执行不同的代码
代码格式如下:
//以下函数返回值都是int 失败都是返回-1
execl("/bin/ls","-a","-l","./",NULL); //使用完整路径
execlp("ls","-a","-l","./",NULL); //使用环境变量路径
char* agv[]={"ls","-a","-l","./",NULL}; //提前定义好
execv("/bin/ls",agv); //使用完整路径,直接调用agv
execvp("ls",agv); //使用环境变量路径,直接调用agv
system("ls -a -l ./"); //与上面不同是当前进程需要等待括号内的程序结束才会继续执行
注:exec函数最后都是NULL空指针作为结束
进程当前被括号内指定的程序替代,但是进程号不变
exec的第一个参数(-a的位置)必须写,随便写东西,不写会导致第一个参数无法正常使用
exec函数会导致exec后的程序功能无法执行,如果想执行后续程序,用fork()函数,创建子进程,靠pid值发别执行不同程序
守护进程(Daemon Process)
概念:
守护进程又叫精灵进程,它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件(始终在后台的进程,无法转到前台,独立于终端故无法被打断)
创建守护进程最简便的方法(不推荐):nohup ./test & //把test进程变为了守护进程
创建方法:①创建子进程,父进程必须退出(exit),进而子进程被1号进程init收养,在后台运行
②通过pid_t setsid();使子进程成为新的会话组长,脱离原来终端
③通过chdir("路径");更改当前工作目录(可以省略的步骤)
④通过umask(0);重设文件权限掩码,设置为0,只影响当前进程(可以省略的步骤)
⑤通过close(0和1和2);关闭所有从父进程继承的打开文件
0--stdin 1--stdout 2--stderr
其他涉及的函数:pid_t getsid(pid_t pid);//查看当前会话组组长
pid_t getpid(void);//获取进程ID
pid_t getpgid(pid_t pid);//获取进程组ID
coding:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
int main(){
int i;
pid_t pid;
pid = fork();//步骤1--创建子进程
if(pid<0){//子进程
perror("fork");
return 0;
}else if(pid>0){//父进程
exit(0);
//sleep(100);
}
printf("I am a deamon\n");
printf("now sid=%d,pid=%d,pgid=%d\n",getsid(getpid()),getpid(),getpgid(getpid()));//查看子进程ID信息
if(setsid()<0){//步骤2--让子进程成为新的会话组组长
perror("setsid");
exit(0);
}
printf("after sid=%d,pid=%d,pgid=%d\n",getsid(getpid()),getpid(),getpgid(getpid()));//查看子进程新的ID信息
chdir("/");//步骤3--改变当前工作目录(可省略步骤)
if(umask(0)<0){//步骤4--重设文件权限掩码(可省略步骤)
perror("unmask");
exit(0);
}
for(i=0;i<3;i++)//步骤5--关闭所有从父进程继承的打开文件
close(i);
printf("after close\n");//不能输出,因为1号标准输输出已关闭
sleep(100);
}
例:创建守护进程,每隔1秒将系统时间写入文件time.txt中
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
int main(int argc, const char *argv[])
{
pid_t pid;
FILE* fp;
time_t t;
int i;
if((pid=fork())<0){
perror("fork");
exit(-1);
}
else if(pid>0)
exit(0);
setsid();
umask(0);
//chdir("/");
for(i=0;i<3;i++){
close(i);
}
if((fp = fopen("time.txt","a")) == NULL){
perror("open");
exit(-1);
}
while(1){
time(&t);
fprintf(fp,"%s",ctime(&t));
fflush(fp);
sleep(1);
}
return 0;
}
GDB调试多进程程序
Start 开始单步运行,n下一步
set follow-fork-mode child 设置GDB调试子进程
set follow-fork-mode parent 设置GDB调试父进程
set detach-on-fork on/off 设置GDB跟踪调试单个进程或多个
on: 只调试父进程或子进程的其中一个,(根据follow-fork-mode来决定),这是默认的模式
off:父子进程都在gdb的控制之下,其中一个进程正常调试(根据follow-fork-mode来决定),另一个进程会被设置为暂停状态。
info inferiors 显示GDB调试的进程
inferiors 进程序号(1,2,3....) 切换GDB调试的进程