LinuxLinux学习之路

APUE读书笔记-17高级进程通信(16)

2020-08-21  本文已影响0人  QuietHeart

服务端

下面,我们将要看到服务进程。

头文件opend.h,版本2

头文件opend.h包含一些标准的头文件以及一些全局变量和函数的声明。

如下所示:

#include "apue.h"
#include <errno.h>

#define CS_OPEN "/home/sar/opend"   /* well-known name */
#define CL_OPEN "open"              /* client's request for server */

extern int   debug;     /* nonzero if interactive (not daemon) */
extern char  errmsg[];  /* error message string to return to client */
extern int   oflag;     /* open flag: O_xxx ... */
extern char *pathname;  /* of file to open for client */

typedef struct {    /* one Client struct per connected client */
  int   fd;         /* fd, or -1 if available */
  uid_t uid;
} Client;

extern Client   *client;        /* ptr to malloc'ed array */
extern int       client_size;   /* # entries in client[] array */

int      cli_args(int, char **);
int      client_add(int, uid_t);
void     client_del(int);
void     loop(void);
void     request(char *, int, int, uid_t);

用来操作客户进程数组的函数

因为服务进程处理所有的客户进程请求,它必须维护每个客户连接的状态。这个通过一个opend.h中的Client数组来做到。

下面代码就定义了操作这个数组的三个函数:

#include    "opend.h"
#define NALLOC  10   /* # client structs to alloc/realloc for */
static void client_alloc(void)   /* alloc more entries in the client[] array */
{
    int     i;

    if (client == NULL)
        client = malloc(NALLOC * sizeof(Client));
    else
        client = realloc(client, (client_size+NALLOC)*sizeof(Client));
    if (client == NULL)
        err_sys("can't alloc for client array");

    /* initialize the new entries */
    for (i = client_size; i < client_size + NALLOC; i++)
        client[i].fd = -1;  /* fd of -1 means entry available */

    client_size += NALLOC;
}
/*
 * Called by loop() when connection request from a new client arrives.
 */
int client_add(int fd, uid_t uid)
{
    int     i;

    if (client == NULL)     /* first time we're called */
        client_alloc();
again:
    for (i = 0; i < client_size; i++) {
        if (client[i].fd == -1) {   /* find an available entry */
            client[i].fd = fd;
            client[i].uid = uid;
            return(i);  /* return index in client[] array */
        }
    }
    /* client array full, time to realloc for more */
    client_alloc();
    goto again;     /* and search again (will work this time) */
}
/*
 * Called by loop() when we're done with a client.
 */
void client_del(int fd)
{
    int     i;
    for (i = 0; i < client_size; i++) {
        if (client[i].fd == fd) {
            client[i].fd = -1;
            return;
        }
    }
    log_quit("can't find client entry for fd %d", fd);
}

client_add第一次被调用时,会调用client_alloc给数组分配10个条目的空间。当这10个条目都被使用完了之后,后面对client_add的调用会导致realloc再次分配额外的空间。通过用这个方式动态分配额外的空间,我们不用在编译之前限制客户进程数组的数目。因为服务进程是一个守护进程,所以以上函数如果出现了错误,我们使用之前定义的log_函数来提示错误信息。

服务进程的main函数,版本2

下面的代码中,main函数定义了全局变量,处理了命令行选项,然后调用函数循环。如果我们使用-d选项启动服务进程,那么服务进程会以交互的方式运行而不是守护进程了。当测试服务进程的时候,这个会被使用。

#include    "opend.h"
#include    <syslog.h>

int      debug, oflag, client_size, log_to_stderr;
char     errmsg[MAXLINE];
char    *pathname;
Client  *client = NULL;

int main(int argc, char *argv[])
{
    int     c;

    log_open("open.serv", LOG_PID, LOG_USER);

    opterr = 0;     /* don't want getopt() writing to stderr */
    while ((c = getopt(argc, argv, "d")) != EOF) {
        switch (c) {
        case 'd':       /* debug */
            debug = log_to_stderr = 1;
            break;

        case '?':
            err_quit("unrecognized option: -%c", optopt);
        }
    }

    if (debug == 0)
        daemonize("opend");

    loop();     /* never returns */
}
上一篇下一篇

猜你喜欢

热点阅读