第13章 Posix共享内存区

13.2 shm_open()和shm_unlink()函数

#include <sys/mman.h>
#include <sys/stat.h>        /* For mode constants */
#include <fcntl.h>           /* For O_* constants */

int shm_open(const char *name, int oflag, mode_t mode);
int shm_unlink(const char *name);
                                            Link with -lrt.
  • oflag:必须含有O_RDONLY或O_RDWR
    • O_CREAT|O_EXCL :已存在会返回错误
    • O_RDWR | O_TRUNC :共享内存区对象已存在时,长度将被截短为0

13.3 ftruncate和truncate

#include <unistd.h>
#include <sys/types.h>

int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
  • 对于普通文件;
    • 文件大小>length:额外数据被丢弃
    • 文件大小
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *pathname, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);
  • stat的结构如下:
struct stat {
   dev_t     st_dev;         /* ID of device containing file */
   ino_t     st_ino;         /* inode number */
   mode_t    st_mode;        /* protection */
   nlink_t   st_nlink;       /* number of hard links */
   uid_t     st_uid;         /* user ID of owner */
   gid_t     st_gid;         /* group ID of owner */
   dev_t     st_rdev;        /* device ID (if special file) */
   off_t     st_size;        /* total size, in bytes */
   blksize_t st_blksize;     /* blocksize for filesystem I/O */
   blkcnt_t  st_blocks;      /* number of 512B blocks allocated */

   /* Since Linux 2.6, the kernel supports nanosecond
      precision for the following timestamp fields.
      For the details before Linux 2.6, see NOTES. */

   struct timespec st_atim;  /* time of last access */
   struct timespec st_mtim;  /* time of last modification */
   struct timespec st_ctim;  /* time of last status change */

#define st_atime st_atim.tv_sec      /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};

13.4 举例子

  • server.c
#include    "cliserv2.h"

int main(int argc, char **argv)
{
    int     fd, index, lastnoverflow, temp;
    long    offset;
    struct shmstruct    *ptr;

    if (argc != 2)
        err_quit("usage: server2 <name>");

        /* 4create shm, set its size, map it, close descriptor */
    shm_unlink(Px_ipc_name(argv[1]));       /* OK if this fails */
    fd = Shm_open(Px_ipc_name(argv[1]), O_RDWR | O_CREAT | O_EXCL, FILE_MODE);
    ptr = Mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE,
               MAP_SHARED, fd, 0);
    Ftruncate(fd, sizeof(struct shmstruct));
    Close(fd);

        /* 4initialize the array of offsets */
    for (index = 0; index < NMESG; index++)
        ptr->msgoff[index] = index * MESGSIZE;

        /* 4initialize the semaphores in shared memory */
    Sem_init(&ptr->mutex, 1, 1);
    Sem_init(&ptr->nempty, 1, NMESG);
    Sem_init(&ptr->nstored, 1, 0);
    Sem_init(&ptr->noverflowmutex, 1, 1);

        /* 4this program is the consumer */
    index = 0;
    lastnoverflow = 0;
    for ( ; ; ) {
        Sem_wait(&ptr->nstored);
        Sem_wait(&ptr->mutex);
        offset = ptr->msgoff[index];
        printf("index = %d: %s\n", index, &ptr->msgdata[offset]);
        if (++index >= NMESG)
            index = 0;              /* circular buffer */
        Sem_post(&ptr->mutex);
        Sem_post(&ptr->nempty);

        Sem_wait(&ptr->noverflowmutex);
        temp = ptr->noverflow;      /* don't printf while mutex held */
        Sem_post(&ptr->noverflowmutex);
        if (temp != lastnoverflow) {
            printf("noverflow = %d\n", temp);
            lastnoverflow = temp;
        }
    }

    exit(0);
}
  • client.c
#include    "cliserv2.h"

int main(int argc, char **argv)
{
    int     fd, i, nloop, nusec;
    pid_t   pid;
    char    mesg[MESGSIZE];
    long    offset;
    struct shmstruct    *ptr;

    if (argc != 4)
        err_quit("usage: client2 <name> <#loops> <#usec>");
    nloop = atoi(argv[2]);
    nusec = atoi(argv[3]);

        /* 4open and map shared memory that server must create */
    fd = Shm_open(Px_ipc_name(argv[1]), O_RDWR, FILE_MODE);
    ptr = Mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE,
               MAP_SHARED, fd, 0);
    Close(fd);

    pid = getpid();
    for (i = 0; i < nloop; i++) {
        Sleep_us(nusec);
        snprintf(mesg, MESGSIZE, "pid %ld: message %d", (long) pid, i);

        if (sem_trywait(&ptr->nempty) == -1) {
            if (errno == EAGAIN) {
                Sem_wait(&ptr->noverflowmutex);
                ptr->noverflow++;
                Sem_post(&ptr->noverflowmutex);
                continue;
            } else
                err_sys("sem_trywait error");
        }
        Sem_wait(&ptr->mutex);
        offset = ptr->msgoff[ptr->nput];
        if (++(ptr->nput) >= NMESG)
            ptr->nput = 0;      /* circular buffer */
        Sem_post(&ptr->mutex);
        strcpy(&ptr->msgdata[offset], mesg);
        Sem_post(&ptr->nstored);
    }
    exit(0);
}

猜你喜欢

转载自blog.csdn.net/qq_36337149/article/details/81318802