c - 在 unp2 书中,为什么 Posix shm 示例会溢出?

标签 c linux

我不太明白下面的代码。为什么会溢出,为什么要使用sem_trywait()?我不能通过旋转 while(sem_trywait(&ptr->nempty) == -1 && errno==EAGAIN); 来重复检查信号量吗?

谢谢, 杰夫

server2.c:

#include        "cliserv2.h"
int main(int argc, char **argv)
{

        int             fd, index, lastnoverflow, temp;
        long    offset;
        struct shmstruct        *ptr;
        char* addr;
        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 */
        addr =Px_ipc_name(argv[1]);
        fd = Shm_open(addr, 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);
}

client2.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);
        }
        msync(ptr, sizeof(struct shmstruct), MS_SYNC);
        munmap(ptr, sizeof(struct shmstruct));
        exit(0);
}

最佳答案

13.6书上解释了溢出计数器的使用:

Overflow counter

The possibility exists that a client wants to send a message but all the message slots are taken. But if the client is actually a server of some type (perhaps an FTP server or an HTTP server), the client does not want to wait for the server to free up a slot. Therefore, we will write our clients so that they do not block but increment the noverflow counter when this happens. (...)

所以,原因是客户端永远不应该阻塞,即使它不能发送消息。正如您所建议的那样,自旋并不比直接使用 sem_wait() 更好,这在本书前面已经介绍过。作者只是演示了如何处理不同的情况,其中不需要阻塞。

关于c - 在 unp2 书中,为什么 Posix shm 示例会溢出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4764740/

相关文章:

linux - 带有额外空格的 Bash 命令替换 : How to solve this?

java - 创建多个 HSQLDB 服务器数据库的最简单方法是什么?

c - linux 内核中 skbuff.h 中的 mac 相关函数如何工作?

c - Linux Kernel vfs_write 函数混淆

c - C 编程中使用 for 循环写入文件

python - 没有这样的文件或目录 : 'gs' linux

c - 如何在 Linux 上检查进程的堆大小

linux - Bash 脚本结果

c - C 中的递归问题

c++ - 将 4 个套接字字节转换为一个 int