linux进程通信、进程控制、exec系统调用

1.信号发送与信号处理

        实验任务与要求:编写C程序,创建子进程,父进程向子进程发送SIGINT信号,子进程捕捉后进行自定义函数的处理,即不是中断子进程的运行,而是输出几条语句,然后恢复默认的信号处理方式。当父进程再次向子进程发送SIGINT信号时,子进程被中断、终止。父进程通过waitpid函数获得导致子进程终止的信号(即SIGINT,也即2),然后输出该信号编号。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

void fun_ctrl_c()
{
    printf("child:recive the sigint signal,execute the user-defined function\n");
    printf("child:restore the default treatment mode immediately\n");
    signal(SIGINT, SIG_DFL);
}

int main()
{
    pid_t pid;
    pid = fork();
    int ret, i, status, wpid;
    if (pid == 0)
    {
        signal(SIGINT, fun_ctrl_c);
        printf("child:this is child,the child pid is: %d\n", getpid());
        sleep(10);
        sleep(10);
        exit(6);
    }
    else
    {
        printf("father:this is father,the father pid is: %d\n", getpid());
        sleep(3);
        if ((ret = kill(pid, SIGINT)) == 0)
        {
            printf("father:father send the signal to child process firstly\n");
        }
        else
        {
            perror("send wrong\n");
        }
        sleep(2);
        if ((ret = kill(pid, SIGINT)) == 0){
            printf("father:father send the signal to child secondly\n");
        }
        else{
            perror("send wrong\n");
        }
        wpid = waitpid(pid, &status, 0);
        printf("father:father process already waited the child terminate\n");
        printf("father:waitpid function return id wpid=%d,child exit state staus=%d\n", wpid, status);
        if (WIFSIGNALED(status))
        {

            i = WTERMSIG(status);
            printf("father:the stop child signal id is:%d\n", i);
            exit(0);
        }
        exit(1);
    }
}

 2.利用守护进程监视指定文件夹的变化

        实验任务与要求:生成一个守护进程,每隔5秒时间监视指定文件夹,中全体文件和文件夹数量的变化,并根据变化情况将结果写入系统日志文件/var/log/syslog中。

        

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<syslog.h>
#include<dirent.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/param.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<string.h>
void init_daemon()
{
	pid_t child1;
	int i;
	child1=fork();
	if(child1>0)
		exit(0);
	else if(child1<0){
		perror("failed in creating the child process\n");
		exit(1);
	}
	setsid();
	chdir("/tmp");
	umask(0);
	for(i=0;i<NOFILE;i++)
		close(i);
	return;
}

int nfile()
{
	DIR *dir;
	struct dirent *ptr;
	int i=0;
	dir=opendir("/root/cht8/dir1/sub");
	while((ptr=readdir(dir))!=NULL){
		if(strcmp(ptr->d_name,"..")&&strcmp(ptr->d_name,"."))
			i++;
	}
	closedir(dir);
	return i;
}

int main()
{
	int nf=0,nnf=0;
	init_daemon();
	nf=nfile();
	openlog("checkNumber",LOG_PID,LOG_DAEMON);
	while(1)
	{
		sleep(1);
		nnf=nfile();
		if(nf<nnf)
		{		
			syslog(LOG_INFO,"There is %d file or folder in the folder you are currently monitoring,%d more files or folders than before\n",nnf,nnf-nf);
		}
		else if(nf>nnf)
		{
			syslog(LOG_INFO,"There is %d file or folder in the folder you are currently monitoring,%d fewer files or folders than before\n",nnf,nnf-nf);
		}
		nf=nnf;
	}
	return 0;
}

注意:首先,启动rsyslog服务:service  rsyslog  start。其次,确认syslog文件存在ls /var/log/syslog ,用touch 你的监视文件路径/1.txt,最后,cat /var/log/syslog就能查看了。

特别注意,记着使用如下命令杀死守护进程,否则后台可能会不停地读写文件或做无意义的运行,造成不必要的资源浪费。

ps  -ef  #查看守护进程的PID,从上述截屏可以看出,希冀平台上守护进程的PID是838

kill  -9  守护进程的PID,例如838

3.理解exec函数族 

实验任务与要求根据如下几个数组的定义,(1依次测试下面6exec族系统调用语句,给出运行结果。请注意:每次运行只复制、粘贴并执行一条exec语句,因为exec语句执行后不再返回,即后续的其它语句将不被执行。2)试述exec之后分别接lvlpvpleve的差异,理解每条语句的执行结果。

char *arg01[]={"ls", "-ld", "sub", NULL };
    char *arg02[]={"ps", "-ef", NULL};
    char *arg03[]={"env", NULL};
char *env1[]={"PATH=/tmp", "USER=jiantao", NULL};

    execl("/usr/bin/who", "who", "-q", NULL);
mkdir("sub", 0644);
    execv("/bin/ls", arg01);

    execlp("ps", "ps", "-ef", NULL);
    execvp("ps", arg02);

    execle("/usr/bin/env", "env", NULL, env1);
execve("/usr/bin/env", arg03, env1);

测试代码:

#include<stdio.h>
#include<unistd.h>
#include<sys/stat.h>
#include<stdlib.h>
#include<sys/types.h>
int main()
{
	char *arg01[]={"ls","-ld","sub",NULL};
	char *arg02[]={"ps", "-ef", NULL};
	char *arg03[]={"env", NULL};
	char *env1[]={"PATH=/tmp", "USER=jiantao", NULL};
	//execl("/usr/bin/who", "who", "-q", NULL);
	//execv("/bin/ls",arg01);
	//execlp("ps", "ps", "-ef", NULL);
	//execvp("ps", arg02);
	//execle("/usr/bin/env", "env", NULL, env1);
	execve("/usr/bin/env", arg03, env1);
	return 1;
}

不同参数的区别:

        1.l(参数列表,List)

        当使用exec后接参数列表时,参数列表中的第一个参数将作为新程序的名称(命令名),而后面的参数将作为该程序的命令行参数。

        通过传递参数列表,可以在执行新程序时向其传递特定的命令行参数。

        2.v(参数向量,Vector)

        当使用exec后接参数向量时,参数向量是一个字符串数组,其中每个字符串都是新程序的命令行参数。

        类似于参数列表,通过传递参数向量,可以在执行新程序时向其传递特定的命令行参数。

       3. lp(本地和持久环境变量,Local and Persistent)

        当使用exec后接本地和持久环境变量时,它是一个环境变量数组,其中每个元素都是以key=value的形式表示的。

        通过传递本地和持久环境变量,可以在执行新程序时设置特定的环境变量。

      4.  vp(全局和持久环境变量,Global and Persistent)

        当使用exec后接全局和持久环境变量时,它也是一个环境变量数组,其中每个元素都是以key=value的形式表示的。

        通过传递全局和持久环境变量,可以在执行新程序时设置特定的环境变量。

      5.  le(本地环境变量,Local Environment)

        当使用exec后接本地环境变量时,它也是一个环境变量数组,其中每个元素都是以key=value的形式表示的。

        通过传递本地环境变量,可以在执行新程序时设置特定的环境变量。

       6. ve(全局环境变量,Global Environment)

        当使用exec后接全局环境变量时,它也是一个环境变量数组,其中每个元素都是以key=value的形式表示的。

        通过传递全局环境变量,可以在执行新程序时设置特定的环境变量。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

南城`烟雨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值