linux-訊息佇列編程執行個體

來源:互聯網
上載者:User

上面是在eclipse下面的工程的編譯情況,這個代碼是來自《PRAISE FOR THE LINUX PROGRAMMING INTERFACE》一書。有三個檔案組成。

/*************************************************************************\*                  Copyright (C) Michael Kerrisk, 2010.                   **                                                                         ** This program is free software. You may use, modify, and redistribute it ** under the terms of the GNU Affero General Public License as published   ** by the Free Software Foundation, either version 3 or (at your option)   ** any later version. This program is distributed without any warranty.    ** See the file COPYING.agpl-v3 for details.                               *\*************************************************************************//* Listing 46-7 */#include <sys/types.h>#include <sys/msg.h>#include <sys/stat.h>#include <stddef.h>                     /* For definition of offsetof() */#include <stdarg.h>                     /* For definition of offsetof() */#include <limits.h>#include <fcntl.h>#include <signal.h>#include <sys/wait.h>#include <sys/types.h>  /* Type definitions used by many programs */#include <stdio.h>      /* Standard I/O functions */#include <stdlib.h>     /* Prototypes of commonly used library functions,                           plus EXIT_SUCCESS and EXIT_FAILURE constants */#include <unistd.h>     /* Prototypes for many system calls */#include <errno.h>      /* Declares errno and defines error constants */#include <string.h>     /* Commonly used string-handling functions */#define SERVER_KEY 0x1aaaaaa1           /* Key for server's message queue */struct requestMsg {                     /* Requests (client to server) */    long mtype;                         /* Unused */    int  clientId;                      /* ID of client's message queue */    char pathname[PATH_MAX];            /* File to be returned */};/* REQ_MSG_SIZE computes size of 'mtext' part of 'requestMsg' structure.   We use offsetof() to handle the possibility that there are padding   bytes between the 'clientId' and 'pathname' fields. */#define REQ_MSG_SIZE (offsetof(struct requestMsg, pathname) - \                      offsetof(struct requestMsg, clientId) + PATH_MAX)#define RESP_MSG_SIZE 8192struct responseMsg {                    /* Responses (server to client) */    long mtype;                         /* One of RESP_MT_* values below */    char data[RESP_MSG_SIZE];           /* File content / response message */};/* Types for response messages sent from server to client */#define RESP_MT_FAILURE 1               /* File couldn't be opened */#define RESP_MT_DATA    2               /* Message contains file data */#define RESP_MT_END     3               /* File data complete */typedef enum { FALSE, TRUE } Boolean;#define min(m,n) ((m) < (n) ? (m) : (n))#define max(m,n) ((m) > (n) ? (m) : (n))static void outputError(Boolean useErr, int err, Boolean flushStdout,const char *format, va_list ap);static void terminate(Boolean useExit3);void usageErr(const char *format, ...);void cmdLineErr(const char *format, ...);void errExit(const char *format, ...);

/*************************************************************************\*                  Copyright (C) Michael Kerrisk, 2010.                   **                                                                         ** This program is free software. You may use, modify, and redistribute it ** under the terms of the GNU Affero General Public License as published   ** by the Free Software Foundation, either version 3 or (at your option)   ** any later version. This program is distributed without any warranty.    ** See the file COPYING.agpl-v3 for details.                               *\*************************************************************************//* Listing 46-9 */#include "svmsg_file.h"static int clientId;static voidremoveQueue(void){    if (msgctl(clientId, IPC_RMID, NULL) == -1)        errExit("msgctl");}static void terminate(Boolean useExit3){    char *s;    /* Dump core if EF_DUMPCORE environment variable is defined and       is a nonempty string; otherwise call exit(3) or _exit(2),       depending on the value of 'useExit3'. */    s = getenv("EF_DUMPCORE");    if (s != NULL && *s != '\0')        abort();    else if (useExit3)        exit(EXIT_FAILURE);    else        _exit(EXIT_FAILURE);}static void outputError(Boolean useErr, int err, Boolean flushStdout,const char *format, va_list ap){#define BUF_SIZE 500#define MAX_ENAME 50    char buf[BUF_SIZE], userMsg[BUF_SIZE], errText[BUF_SIZE],ename[BUF_SIZE];    vsnprintf(userMsg, BUF_SIZE, format, ap);    if (useErr)        snprintf(errText, BUF_SIZE, " [%s %s]",                (err > 0 && err <= MAX_ENAME) ?                ename[err] : "?UNKNOWN?", strerror(err));    else        snprintf(errText, BUF_SIZE, ":");    snprintf(buf, BUF_SIZE, "ERROR%s %s\n", errText, userMsg);    if (flushStdout)        fflush(stdout);       /* Flush any pending stdout */    fputs(buf, stderr);    fflush(stderr);           /* In case stderr is not line-buffered */}void errMsg(const char *format, ...){    va_list argList;    int savedErrno;    savedErrno = errno;       /* In case we change it here */    va_start(argList, format);    outputError(TRUE, errno, TRUE, format, argList);    va_end(argList);    errno = savedErrno;}void usageErr(const char *format, ...){    va_list argList;    fflush(stdout);           /* Flush any pending stdout */    fprintf(stderr, "Usage: ");    va_start(argList, format);    vfprintf(stderr, format, argList);    va_end(argList);    fflush(stderr);           /* In case stderr is not line-buffered */    exit(EXIT_FAILURE);}void cmdLineErr(const char *format, ...){    va_list argList;    fflush(stdout);           /* Flush any pending stdout */    fprintf(stderr, "Command-line usage error: ");    va_start(argList, format);    vfprintf(stderr, format, argList);    va_end(argList);    fflush(stderr);           /* In case stderr is not line-buffered */    exit(EXIT_FAILURE);}void errExit(const char *format, ...){    va_list argList;    va_start(argList, format);    outputError(TRUE, errno, TRUE, format, argList);    va_end(argList);    terminate(TRUE);}int cli(int argc, char *argv[]){    struct requestMsg req;    struct responseMsg resp;    int serverId, numMsgs;    ssize_t msgLen, totBytes;    if (argc != 2 || strcmp(argv[1], "--help") == 0)        usageErr("%s pathname\n", argv[0]);    if (strlen(argv[1]) > sizeof(req.pathname) - 1)        cmdLineErr("pathname too long (max: %ld bytes)\n",                (long) sizeof(req.pathname) - 1);    /* Get server's queue identifier; create queue for response */    serverId = msgget(SERVER_KEY, S_IWUSR);    if (serverId == -1)        errExit("msgget - server message queue");    clientId = msgget(IPC_PRIVATE, S_IRUSR | S_IWUSR | S_IWGRP);    if (clientId == -1)        errExit("msgget - client message queue");    if (atexit(removeQueue) != 0)        errExit("atexit");    /* Send message asking for file named in argv[1] */    req.mtype = 1;                      /* Any type will do */    req.clientId = clientId;    strncpy(req.pathname, argv[1], sizeof(req.pathname) - 1);    req.pathname[sizeof(req.pathname) - 1] = '\0';                                        /* Ensure string is terminated */    if (msgsnd(serverId, &req, REQ_MSG_SIZE, 0) == -1)        errExit("msgsnd");    /* Get first response, which may be failure notification */    msgLen = msgrcv(clientId, &resp, RESP_MSG_SIZE, 0, 0);    if (msgLen == -1)        errExit("msgrcv");    if (resp.mtype == RESP_MT_FAILURE) {        printf("%s\n", resp.data);      /* Display msg from server */        if (msgctl(clientId, IPC_RMID, NULL) == -1)            errExit("msgctl");        exit(EXIT_FAILURE);    }    /* File was opened successfully by server; process messages       (including the one already received) containing file data */    totBytes = msgLen;                  /* Count first message */    for (numMsgs = 1; resp.mtype == RESP_MT_DATA; numMsgs++) {        msgLen = msgrcv(clientId, &resp, RESP_MSG_SIZE, 0, 0);        if (msgLen == -1)            errExit("msgrcv");        printf("%s",resp.data);        totBytes += msgLen;    }    printf("Received %ld bytes (%d messages)\n", (long) totBytes, numMsgs);    exit(EXIT_SUCCESS);}

/*************************************************************************\*                  Copyright (C) Michael Kerrisk, 2010.                   **                                                                         ** This program is free software. You may use, modify, and redistribute it ** under the terms of the GNU Affero General Public License as published   ** by the Free Software Foundation, either version 3 or (at your option)   ** any later version. This program is distributed without any warranty.    ** See the file COPYING.agpl-v3 for details.                               *\*************************************************************************//* Listing 46-8 */#include "svmsg_file.h"//extern  void outputError(Boolean useErr, int err, Boolean flushStdout,const char *format, va_list ap);static void  grimReaper(int sig)             /* SIGCHLD handler */{    int savedErrno;    savedErrno = errno;                 /* waitpid() might change 'errno' */    while (waitpid(-1, NULL, WNOHANG) > 0)        continue;    errno = savedErrno;}static void serveRequest(const struct requestMsg *req)  /* Executed in child process: serve a single client */{    int fd;    ssize_t numRead;    struct responseMsg resp;    fd = open(req->pathname, O_RDONLY);    if (fd == -1) {                     /* Open failed: send error text */        resp.mtype = RESP_MT_FAILURE;        snprintf(resp.data, sizeof(resp.data), "%s", "Couldn't open");        msgsnd(req->clientId, &resp, strlen(resp.data) + 1, 0);        exit(EXIT_FAILURE);             /* and terminate */    }    /* Transmit file contents in messages with type RESP_MT_DATA. We don't       diagnose read() and msgsnd() errors since we can't notify client. */    resp.mtype = RESP_MT_DATA;    while ((numRead = read(fd, resp.data, RESP_MSG_SIZE)) > 0)        if (msgsnd(req->clientId, &resp, numRead, 0) == -1)            break;    /* Send a message of type RESP_MT_END to signify end-of-file */    resp.mtype = RESP_MT_END;    msgsnd(req->clientId, &resp, 0, 0);         /* Zero-length mtext */}int main(int argc, char *argv[]){    struct requestMsg req;    pid_t pid;    ssize_t msgLen;    int serverId;    struct sigaction sa;    /* Create server message queue */    serverId = msgget(SERVER_KEY, IPC_CREAT | IPC_EXCL |                            S_IRUSR | S_IWUSR | S_IWGRP);    if (serverId == -1)        errExit("msgget");    /* Establish SIGCHLD handler to reap terminated children */    sigemptyset(&sa.sa_mask);    sa.sa_flags = SA_RESTART;    sa.sa_handler = grimReaper;    if (sigaction(SIGCHLD, &sa, NULL) == -1)        errExit("sigaction");    /* Read requests, handle each in a separate child process */    for (;;) {        msgLen = msgrcv(serverId, &req, REQ_MSG_SIZE, 0, 0);        if (msgLen == -1) {            if (errno == EINTR)         /* Interrupted by SIGCHLD handler? */                continue;               /* ... then restart msgrcv() */            errMsg("msgrcv");           /* Some other error */            break;                      /* ... so terminate loop */        }        pid = fork();                   /* Create child process */        if (pid == -1) {            errMsg("fork");            break;        }        if (pid == 0) {                 /* Child handles request */            serveRequest(&req);            _exit(EXIT_SUCCESS);        }printf("--------------------------------------------------------\n");        /* Parent loops to receive next client request */    }    /* If msgrcv() or fork() fails, remove server MQ and exit */    if (msgctl(serverId, IPC_RMID, NULL) == -1)        errExit("msgctl");    exit(EXIT_SUCCESS);}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.