我不太明白下面的代码。为什么会溢出,为什么要使用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/