day2--exec函数族+守护进程+GDB调试多进程

本文详细介绍了Linux中的exec函数族,包括execl、execlp、execv和execvp的区别,以及如何创建守护进程,如使用setsid、chdir和umask等技巧。同时,还提到了GDB调试多进程程序的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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调试的进程

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@Cabbage

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值