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
- shm_unlink函数删除一个共享内存区对象的名字不会影响其底层支撑对象的现有引用,直到对于该对象的引用全部关闭为止,仅仅防止后续的open调用取得成功
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);
int fstat(int fd,struct stat *buf);
-
对于普通文件;
- 文件大小>length:额外数据被丢弃
- 文件大小<length:文件是否被修改未说明,不过几乎所有linux都支持truncate扩展文件
-
对共享内存区对象
- 把文件大小设置为length字节
-
使用fstat获取对象的信息
#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);
}