原理
一、setsid();
VFS 层系统调用
int sys_setsid(void)
{
...
current->leader = 1;
current->session = current->pgrd = current->pid;
current->tty = -1; //表示该领头进程没有控制终端。
...
}
说明:当进程是会话的领头进程时setsid()调用失败并返回(-1)。setsid()调用成功后,返回新的会话的ID,调用setsid函数的进程成为新的会话的领头进程,并与其父进程的会话组和进程组脱离。由于会话对控制终端的独占性,进程同时与控制终端脱离。
pid_t pid = fork(); //fork a process
if (pid < 0) exit(0); //fork error
if (pid > 0) exit(0); //father process exit
setsid();[1] //creat a new session for a process
//之前parent和child运行在同一个session里,parent是会话(session)的领头进程,
//parent进程作为会话的领头进程,如果exit结束执行的话,那么子进程会成为孤儿进程,并被init收养。
//执行setsid()之后,child将重新获得一个新的会话(session)id。
//这时parent退出之后,将不会影响到child了。
二、umask 一般与 int open(const char *pathname, int flags, mode_t mode)合用
每个文件都有权限,每新创建一个文件就要指定文件权限 (mode &umask)
新创建的文件 pathname 的 文件权限 = (umask & mode)
#include <fcntl.h>
int main()
{
int fd;
umask(0026);
fd = open("test.txt",O_RDWR | O_CREAT ,0666);
if(fd < 0)
perror("open");
return 0;
}
文件权限结果为 666 - 26 = 640 = rw-r-----
三、getdtablesize ()
这个函数定义为__sysconf(open_max)形式,getdtablesize ()是返回所在进程的文件描述附表的项数,即该进程打开的文件数目
四、什么是linux 的"重定向"???
Linux重定向是指修改原来默认的一些东西,对原来系统命令的默认执行方式进行改变,比如说简单的我不想看到在显示器的输出而是希望输出到某一文件中就可以通过Linux重定向来进行这项工作。
实验步骤
守护进程编写的主要步骤如下:
1) 将程序进入后台执行。由于守护进程最终脱离控制终端,到后台去运行。方法是在进程中调用 fork 使父进程终止,让 Daemon 在子进程中后台执行。这就是常说的“脱壳”。子进程继续函数 fork()的定义如
下:pid_t fork(void);
2) 脱离控制终端、登录会话和进程组。开发人员如果要摆脱它们,不受它们的影响,一般使用 setsid() 设置新会话的领头进程,并与原来的登录会话和进程组脱离。
3) 禁止进程重新打开控制终端。
4) 重设文件权限掩码
5) 关闭打开的文件描述符,并重定向标准输入、标准输出和标准错误输出的文件描述符。进程从创建它的父进程那里继承了打开的文件描述符。如果不关闭,将会浪费系统资源,引起无法预料的错误。关
闭三者的代码如下:for (fd = 0, fdtablesize = getdtablesize(); fd < fdtablesize; fd++) close(fd);
6) 改变工作目录到根目录或特定目录进程活动时,其工作目录所在的文件系统不能卸下守护进程实例包括两部分:主程序 test.c 和初始化程序 init.c。主程序每隔一分钟向/tmp 目录中的日志test.log 报告运行状态。初始化程序中的 init_daemon 函数负责生成守护进程。读者可以利用 init_daemon函数生成自己的守护进程。
实验代码
init.c
#include < unistd.h >
#include < sys/types.h >
#include < sys/stat.h >
#include <stdlib.h>
void init_daemon(void)
{
int pid;
int i;
if (pid = fork()) { exit(0); } //是父进程,结束父进程
else if (pid < 0) { exit( -1 ); } //fork 失败,退出
setsid(); //第一子进程成为新的会话组长和进程组长
//并与控制终端分离
if (pid = fork()) { exit(0); } //是第一子进程,结束第一子进程
else if (pid < 0) { exit(1); } //fork 失败,退出
//第二子进程不再是会话组长
for(i=0; i< getdtablesize(); ++i) //关闭打开的文件描述符
close(i);
chdir("/tmp"); //改变工作目录到 /tmp
umask(0); //重设文件创建掩模
return;
} 测试程序test.c
#include <stdio.h>
#include <time.h>
void init_daemon(void);
//守护进程初始化函数
int main(){
FILE *fp;
time_t t;
init_daemon();
//初始化为 Daemon
while(1) //每隔 2 秒钟向 test.log 报告运行状态
{
sleep(2); //睡眠 2 秒钟
if((fp = fopen("test.log","a")) != NULL)
{
t=time(0);
fprintf(fp,"I'm here at %sn",asctime(localtime(&t)) );
fclose(fp);
}
}
return 0;
}
编译:
[root@vm root]#gcc –g –o test init.c test.c
执行:
[root@vm root]#./test
查看进程: [root@vm root]#ps –ef
从输出可以发现 test 守护进程的各种特性满足上面的要求。
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com