linux c 双进程守护,[linux c]Linux 系统守护进程实验

原理

一、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

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

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

#include

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 守护进程的各种特性满足上面的要求。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值