相关的API函数
•int shm_open (const char *name, int oflag, mode_t mode);
•int shm_unlink (const char *name);
•int ftruncate (int fd, off_t length);
•int fstat (int fd, struct stat *buf);
•void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
•int munmap (void *addr, size_t length);
ftruncate
函数功能:改变文件大小
相关函数:open、truncate
表头文件:#include <unistd.h>
函数原型:int ftruncate(int fd, off_t length)
函数说明:ftruncate()会将参数fd指定的文件大小改为参数length指定的大小。参数fd为已打开的文件描述词,而且必须是以写入模式打开的文件。如果原来的文件件大小比参数length大,则超过的部分会被删去
返 回 值:0、-1
错误原因:errno
EBADF 参数fd文件描述词为无效的或该文件已关闭
EINVAL 参数fd为一socket并非文件,或是该文件并非以写入模式打开
munmap
函数说明 munmap()用来取消参数start所指的映射内存起始地址,参数length则是欲取消的内存大小。当进程结束或利用exec相关函数来执行其他程序时,映射内存会自动解除,但关闭对应的文件描述符时不会解除映射。
munmap(解除内存映射)
相关函数 mmap
表头文件 #include<unistd.h>
#include<sys/mman.h>
定义函数 int munmap(void *start,size_t length);
函数说明 munmap()用来取消参数start所指的映射内存起始地址,参数length则是欲取消的内存大小。当进程结束或利用exec相关函数来执行其他程序时,映射内存会自动解除,但关闭对应的文件描述符时不会解除映射。
返回值 如果解除映射成功则返回0,否则返回-1,错误原因存于errno中错误代码EINVAL
简单的共享内存读写示例
read
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define SHM_NAME "/shm"
int main (void)
{
int shm_fd;
shm_fd = shm_open (SHM_NAME, O_RDWR | O_CREAT, 0);
if (shm_fd < 0)
{
perror ("shm_open");
return -1;
}
ftruncate (shm_fd, 8192);
struct stat filestat;
fstat (shm_fd, &filestat);
printf ("st_size: %ld\n", filestat.st_size);
char *shm_ptr;
shm_ptr = (char*)mmap (NULL, filestat.st_size, \
PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0);
close (shm_fd);
printf ("pid %d: %s\n", getpid(), shm_ptr);
munmap (shm_ptr, filestat.st_size);
shm_unlink (SHM_NAME);
return 0;
}
write
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#define SHM_NAME "/shm"
int main (void)
{
int shm_fd;
shm_fd = shm_open (SHM_NAME, O_RDWR | O_CREAT, 0666);
if (shm_fd < 0)
{
perror ("shm_open");
return -1;
}
ftruncate (shm_fd, 8192);
struct stat filestat;
fstat (shm_fd, &filestat);
printf ("st_size: %ld\n", filestat.st_size);
char *shm_ptr;
shm_ptr = (char*)mmap (NULL, filestat.st_size, \
PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0);
close (shm_fd);
char buf[] = "hello world";
memmove (shm_ptr, buf, sizeof (buf));
printf ("pid %d: %s\n", getpid(), shm_ptr);
munmap (shm_ptr, filestat.st_size);
return 0;
}
信号量和共享内存 使用示例
write
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#define SHM_NAME "/memmap"
#define SEM_NAME "/memmap_sem"
int main (void)
{
int shm_fd;
sem_t *sem;
shm_fd = shm_open (SHM_NAME, O_RDWR | O_CREAT, 0666);
sem = sem_open (SEM_NAME, O_CREAT, 0666, 0);
if (shm_fd < 0 || sem == SEM_FAILED)
{
perror ("open");
return -1;
}
ftruncate (shm_fd, 8192);
struct stat filestat;
fstat (shm_fd, &filestat);
printf ("st_size: %ld\n", filestat.st_size);
char *shm_ptr;
shm_ptr = (char*)mmap (NULL, filestat.st_size, \
PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0);
close (shm_fd);
char msg[] = "hello world";
memmove (shm_ptr, msg, sizeof (msg));
printf ("pid %d: %s\n", getpid(), shm_ptr);
sem_post (sem);
sem_close (sem);
sleep (5);
munmap (shm_ptr, 8192);
return 0;
}
read
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define SHM_NAME "/memmap"
#define SEM_NAME "/memmap_sem"
int main (void)
{
int shm_fd;
sem_t *sem;
shm_fd = shm_open (SHM_NAME, O_RDWR|O_CREAT, 0666);
sem = sem_open (SEM_NAME, 0);
if (shm_fd < 0 || sem == SEM_FAILED)
{
perror ("open");
return -1;
}
ftruncate (shm_fd, 8192);
struct stat filestat;
fstat (shm_fd, &filestat);
printf ("st_size: %ld\n", filestat.st_size);
char *shm_ptr;
shm_ptr = (char*)mmap (NULL, filestat.st_size, PROT_READ|PROT_WRITE, \
MAP_SHARED, shm_fd, 0);
if (shm_ptr ==(void*)-1)
{
perror ("mmap");
exit (-1);
}
close (shm_fd);
sem_wait (sem);
printf ("pid %d: %s\n", getpid(), shm_ptr);
sem_close (sem);
munmap (shm_ptr, 8192);
shm_unlink (SHM_NAME);
sem_unlink (SEM_NAME);
return 0;
}