查看: 2200|回复: 0

嵌入式系统中守护进程的编写及调试

[复制链接]
  • TA的每日心情
    开心
    2013-12-17 13:39
  • 签到天数: 48 天

    连续签到: 1 天

    [LV.5]常住居民I

    发表于 2013-12-20 09:52:45 | 显示全部楼层 |阅读模式
    分享到:
    守护进程是Linux系统开发中很重要的知识点,很多朋友对这个问题掌握的不是很深入,今天我就写写这方面的问题,可以帮助大家熟悉守护进程的编写过程。

    守护进程编写的主要步骤如下:
    1.屏蔽一些有关控制终端操作的信号。防止在守护进程没有正常运转起来时,控制终端受到干扰退出或挂起。
    signal(SIGTTOU,SIG_IGN);
      signal(SIGTTIN,SIG_IGN);
      signal(SIGTSTP,SIG_IGN);
      signal(SIGHUP ,SIG_IGN);
    2.  将程序进入后台执行。由于守护进程最终脱离控制终端,到后台去运行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。这就是常说的“脱壳”。子进程继续函数fork()的定义如下:
      pid_t fork(void);
    3.  脱离控制终端、登录会话和进程组。开发人员如果要摆脱它们,不受它们的影响,一般使用setsid() 设置新会话的领头进程,并与原来的登录会话和进程组脱离。
    4.  禁止进程重新打开控制终端。
    5.  关闭打开的文件描述符,并重定向标准输入、标准输出和标准错误输出的文件描述符。进程从创建它的父进程那里继承了打开的文件描述符。如果不关闭,将会浪费系统资源,引起无法预料的错误。关闭三者的代码如下:
      for (fd = 0, fdtablesize = getdtablesize();
      fd < fdtablesize; fd++)
      close(fd);
    6.  改变工作目录到根目录或特定目录进程活动时,其工作目录所在的文件系统不能卸下
    7.  处理SIGCHLD信号。SIGCHLD信号是子进程结束时,向内核发送的信号。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。因此需要对SIGCHLD信号做出处理,回收僵尸进程的资源,避免造成不必要的资源浪费。可以用如下语句:
      signal(SIGCHLD,(void *)reap_status);
      捕捉信号SIGCHLD,用下面的函数进行处理:
      void reap_status()
      { int pid;
            ….
                       }
    程序:
    init.c test.c
    实验内容及步骤
    守护进程实例包括两部分:主程序test.c和初始化程序init.c。主程序每隔一分钟向/tmp目录中的日志test.log报告运行状态。初始化程序中的init_daemon函数负责生成守护进程。读者可以利用init_daemon函数生成自己的守护进程。
    1. init.c
    #include < unistd.h >
    #include < signal.h >
    #include < sys/param.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< NOFILE;++i)//关闭打开的文件描述符
    close(i);
    chdir("/tmp");//改变工作目录到/tmp
    umask(0);//重设文件创建掩模
    return;
    }
    2. test.c
    #include < stdio.h >
    #include < time.h >
    void init_daemon(void);//守护进程初始化函数
    int main() {
    FILE *fp;
    time_t t;
    init_daemon();//初始化为Daemon
    while(1)//每隔一分钟向test.log报告运行状态
    {
    sleep(60);//睡眠一分钟
    if((fp=fopen("test.log","a")) >=0)
    {
    t=time(0);
    fprintf(fp,"I'm here at %sn",asctime(localtime(&t)) );
    fclose(fp);
    }
    }
    }
    编译:               [root@vm root]#gcc –g –o test init.c test.c
    执行:               [root@vm root]#./test
    查看进程:      [root@vm root]#ps –ef
    从输出可以发现test守护进程的各种特性满足上面的要求,这个问题掌握了,会在嵌入式开发中如虎添翼!!!
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-12-12 10:46 , Processed in 0.112317 second(s), 14 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.