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)依次测试下面的6条exec族系统调用语句,给出运行结果。请注意:每次运行只复制、粘贴并执行一条exec语句,因为exec语句执行后不再返回,即后续的其它语句将不被执行。(2)试述exec之后分别接l、v、lp、vp、le、ve的差异,理解每条语句的执行结果。
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的形式表示的。
通过传递全局环境变量,可以在执行新程序时设置特定的环境变量。