第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
  • 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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值