守护进程

守护进程创建

/*************************************************************************
    > File Name: daemon.c
    > Author: ICKelin
    > Mail: [email protected] 
    > Created Time: 2014年12月18日 星期四 01时04分59秒
 ************************************************************************/

#include<stdio.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <syslog.h>
#include <signal.h>
#include <stdlib.h>

/*
 * 守护进程
 *  守护进程
 *  创建守护进程
 *        umask(0)
 *        fork()&exit(0)
 *        setsid()
 *        chdir()
 *        getrlimit&close(i)
 *
 * */
void daemonize(const char *cmd)
{
    int                    i,fd0, fd1, fd2;
    pid_t                pid;
    struct rlimit        rl;
    struct sigaction    sa;
    //清除
    umask(0);

    //获取最大文件描述符号
    if(getrlimit(RLIMIT_NOFILE, &rl) < 0)
        error("getrlimit");

    //会话组,进程组组长
    if( (pid = fork()) < 0)
        error("fork");
    else if(pid > 0)
        exit(0);        //停止父进程
    setsid();

    sa.sa_handler = SIG_IGN;        //忽略
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if(sigaction(SIGHUP, &sa, NULL) < 0)
        error("ignore SIGHUB");
    if((pid = fork()) < 0)
        error("fork");
    else if(pid != 0)
        exit(0);
    //修改当前工作路径
    if(chdir("/") < 0)
        error("chdir");
    //关闭文件描述符
    for(i = 0; i< rl.rlim_max; i++)
        close(i);
    fd0 = open("/dev/null", O_RDWR);
    fd1 = dup(0);
    fd2 = dup(0);

    //初始化log
    openlog(cmd, LOG_CONS, LOG_DAEMON);
    if(fd0 !=0 || fd1 != 1 || fd2 != 2)
    {
        syslog(LOG_ERR,"unexpected file descriptors %d %d %d", fd0, fd1, fd2);
        exit(1);
    }
}

int main(int argc,char *argv[])
{
    daemonize("daemon");
}

服务器端守护进程

/*************************************************************************
    > File Name: demo04.c
    > Author: ICKelin
    > Mail: [email protected] 
    > Created Time: 2014年12月07日 星期日 15时17分48秒
 ************************************************************************/

#include"net.h"
#include <syslog.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/resource.h>

void daemonize(const char *cmd)
{
    int                    i,fd0, fd1, fd2;
    pid_t                pid;
    struct rlimit        rl;
    struct sigaction    sa;
    //清除
    umask(0);

    //获取最大文件描述符号
    if(getrlimit(RLIMIT_NOFILE, &rl) < 0)
        error("getrlimit");

    //会话组,进程组组长
    if( (pid = fork()) < 0)
        error("fork");
    else if(pid > 0)
        exit(0);        //停止父进程
    setsid();

    sa.sa_handler = SIG_IGN;        //忽略
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if(sigaction(SIGHUP, &sa, NULL) < 0)
        error("ignore SIGHUB");
    if((pid = fork()) < 0)
        error("fork");
    else if(pid != 0)
        exit(0);
    //修改当前工作路径
    if(chdir("/") < 0)
        error("chdir");
    //关闭文件描述符
    for(i = 0; i< rl.rlim_max; i++)
        close(i);
    fd0 = open("/dev/null", O_RDWR);
    fd1 = dup(0);
    fd2 = dup(0);

    //初始化log
    openlog(cmd, LOG_CONS, LOG_DAEMON);
    if(fd0 !=0 || fd1 != 1 || fd2 != 2)
    {
        syslog(LOG_ERR,"unexpected file descriptors %d %d %d", fd0, fd1, fd2);
        exit(1);
    }
}

int main(int argc,char *argv[])
{
    if(argc != 2)
        error("arguemtne");
    daemonize("server");
    unsigned int port = atoi( argv[1]);
    
    int server = setup(port);
    if(server ==-1)
        error("setup");

    fprintf(stdout,"server start\nlistenning port %d\n",port);
    struct sockaddr_storage client_addr;
    unsigned int address_size = sizeof(client_addr);
    
    while(1)
    {
        int client = accept(server,(struct sockaddr*)&client_addr,&address_size);
        do_connect(client,client_thread,(void *)client);
    }
    close(server);
    return 0;
}

net.h头文件

/*************************************************************************
    > File Name: demo03.c
    > Author: ICKelin
    > Mail: [email protected] 
    > Created Time: 2014年12月07日 星期日 11时53分24秒
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<errno.h>
#include<pthread.h>
#include<unistd.h>

static int count = 0;

/* 致命错误处理包裹函数 */
void error(char *msg)
{
    fprintf(stderr,"%s error with:%s\n",msg, strerror(errno));
    exit(1);
}

/* 服务器启动函数 
 * 接收端口号
 * 绑定,监听
 * 返回服务器端套接字描述符
 *
 * */
int setup(unsigned int port)
{
    struct sockaddr_in server_sock;
    int fd = -1;
    fd = socket(PF_INET, SOCK_STREAM, 0);

    int reuse = 1;
    if(setsockopt(fd,SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(int)) == -1)
        error("set reuse");
    if(fd == -1)
        error("socket");
    server_sock.sin_family = PF_INET;
    server_sock.sin_port = (in_port_t)htons(port);
    server_sock.sin_addr.s_addr = htonl(INADDR_ANY);

    int c = bind(fd, (struct sockaddr *)&server_sock, sizeof(server_sock));
    if(c == -1)
        error("bind");
    if(listen(fd,10) == -1)
        error("listen");
    return fd;
}

/* 连接处理线程
 *
 * 接收连接套接子描述符
 * 处理请求
 * 返回空
 * */

void client_thread(int connect_d)
{
    char *msg = "welcome to my server --ICKelin\n";
    
    fprintf(stdout,"new connect, current connect count %d\n",++count);
    sleep(5);
    if(send(connect_d, msg, strlen(msg),0) <0)
    {
        error("send");
    }

    close(connect_d);
    count--;
}

/*
 * 处理连接
 * 接收客户端连接,和处理线程
 * 返回空
 * */

void do_connect(int connect_d,void *func,void *args)
{
    pthread_t newthread;
    if ( pthread_create(&newthread,NULL,func,args) == -1)
        error("pthread_create");
}

/*
 * 关闭连接
 * */
void close_connect(int fd)
{
    close(fd);
}

由于前后编写时间间隔比较长,代码前后搭配不当,正确的做法是,将net.h里面输出到标准输出,标准错误相关代码利用syslog输出到日志。

编译执行

hadoop@ICKelin:~/Network/2014_12_07$ gcc demo04.c -lpthread -o myserver1111111
hadoop@ICKelin:~/Network/2014_12_07$ ./myserver1111111 5002
hadoop@ICKelin:~/Network/2014_12_07$ ps -axj|grep myserver1111111 
Warning: bad ps syntax, perhaps a bogus -? See http://procps.sf.net/faq.html
    1  8313  8312  8312 ?           -1 S     1000   0:00 ./myserver1111111 5002
 8035  8319  8318  8035 pts/0     8318 S+    1000   0:00 grep --color=auto myserver1111111
hadoop@ICKelin:~/Network/2014_12_07$ 

用kill杀死。kill 8313

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。