这一节中用到的技术点有:信号、多进程、exec函数
exec函数族
exec的本质
exec是用参数中指定的程序替换了当前进程的正文段、数据段、堆和栈。
如果调用失败会继续运行当前进程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
if (argc < 3)
{
printf("Using:./procctl timetvl program argv ...\n");
printf("Example:~/project/tools2/c/procctl 60 ~/project/idc2/c/crtsurfdata5 ~/project/idc2/init/stcode.ini ~/tmp/surfdata/ ~/log/idc/crtsurfdata5.log xml,json,csv \n\n");
printf("本程序是服务程序的调度程序,周期性启动服务程序或shell脚本。\n");
printf("timetvl 运行周期,单位:秒。被调度的程序运行结束后,在timetvl秒后会被procctl重新启动。\n");
printf("program 被调度的程序名,必须使用全路径。\n");
printf("argvs 被调度的程序的参数。\n");
printf("注意,本程序不会被kill杀死,但可以用kill -9强行杀死。\n\n\n");
return -1;
}
// 关闭信号和IO,本程序不希望被打扰。
for (int i = 0; i < 64; i++)
{
signal(i, SIG_IGN);
close(i);
}
// 生成子进程,父进程退出,让程序运行在后台,由系统1号进程托管。
if (fork() != 0)
exit(0);
// 启用SIGCHLD信号,让父进程可以wait子进程退出的状态。
signal(SIGCHLD, SIG_DFL);
char *pargv[argc];
for (int i = 2; i < argc; i++)
pargv[i - 2] = argv[i];
pargv[argc - 2] = NULL;
while (true)
{
if (fork() == 0)
{
execv(argv[2], pargv);
exit(0);
}
else
{
int status;
wait(&status);
sleep(atoi(argv[1]));
}
}
}