Linux IPC实践(10) --Posix共享内存
1.?創建/獲取一個共享內存
#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);參數:
? ?name:? 共享內存名字;
? ?oflag: 與open函數類型,?可以是O_RDONLY,?O_WRONLY,?O_RDWR,?還可以按位或上O_CREAT,?O_EXCL,?O_TRUNC.
? ?mode: 此參數總是需要設置,?如果oflag沒有指定O_CREAT,?則mode可以設置為0;
返回值:
? ?成功:?返回一個文件描述符;
? ?失敗:?返回-1;
注意-Posix?IPC名字限制:
? ?1.?必須以”/”開頭,?并且后面不能還有”/”,?形如:/file-name;
? ?2.?名字長度不能超過NAME_MAX
? ?3.?鏈接時:Link?with?-lrt.
/** 示例: 共享內存的打開與關閉 **/ int main(int argc,char *argv[]) {int shmid = shm_open("/xyz", O_RDWR|O_CREAT, 0666);if (shmid == -1)err_exit("shmget error");cout << "share memory open success" << endl;close(shmid); }2.?修改共享內存大小
int ftruncate(int fd, off_t length);該函數不僅可用于修改共享內存大小,?而且可以用于修改文件大小
/** 示例: 修改共享內存大小 將其修改為一個Student結構體的大小 **/ struct Student {char name[32];int age; }; int main(int argc,char *argv[]) {int shmid = shm_open("/xyz", O_RDWR|O_CREAT, 0666);if (shmid == -1)err_exit("shmget error");if (ftruncate(shmid, sizeof(Student)) == -1)err_exit("ftruncate error");cout << "share memory change size success" << endl;close(shmid); }3.?獲取共享內存狀態
int fstat(int fd, struct stat *buf);該函數不僅可用于獲取共享內存狀態,?而且可以用于獲取文件狀態,?與前面曾經講述過的stat,?lstat類型;
//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 */time_t st_atime; /* time of last access */time_t st_mtime; /* time of last modification */time_t st_ctime; /* time of last status change */ }; /** 示例: 獲取共享內存的mode和size **/ int main(int argc,char *argv[]) {int shmid = shm_open("/xyz", O_RDWR|O_CREAT, 0666);if (shmid == -1)err_exit("shmget error");if (ftruncate(shmid, sizeof(Student)) == -1)err_exit("ftruncate error");struct stat buf;if (fstat(shmid, &buf) == -1)err_exit("lstat error");// 注意: 獲取權限時, 需要&上0777, 而且要以%o, 八進制方式打印printf("mode: %o\n", buf.st_mode&0777);printf("size: %ld\n", buf.st_size);close(shmid); }4.?刪除一個共享內存對象
int shm_unlink(const char *name); //示例: int main(int argc,char *argv[]) {shm_unlink("/xyz"); }5.?共享內存的映射/卸載
#include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *addr, size_t length);參數:
? ?addr:? 要映射的起始地址,?通常指定為NULL,?讓內核自動選擇;
? ?length: 映射到進程地址空間的字節數,?通常是先前已經創建的共享內存的大小;
? ?prot: 映射區保護方式(見下);
? ?flags: 標志(通常指定為MAP_SHARED,?用于進程間通信);
? ?fd: 文件描述符(填為shm_open返回的共享內存ID);
? ?offset: 從文件頭開始的偏移量(一般填為0);
?
prot | 說明 |
PROT_READ | 頁面可讀 |
PROT_WRITE | 頁面可寫 |
PROC_EXEC | 頁面可執行 |
PROC_NONE | 頁面不可訪問 |
?
flags | 說明 |
MAP_SHARED | 變動是共享的 |
MAP_PRIVATE | 變動是私有的 |
MAP_FIXED | 準確解釋addr參數,?如果不指定該參數,?則會以4K大小的內存進行對齊 |
MAP_ANONYMOUS | 建立匿名映射區,?不涉及文件 |
?
mmap返回值:
? ?成功:?返回映射到的內存區的起始地址;
? ?失敗:?返回MAP_FAILED;
注意:mmap失敗返回EACCES錯誤的原因:
? ?EACCES?A?file?descriptor?refers?to?a?non-regular?file.??
Or?MAP_PRIVATE?was?requested,?but?fd??is??not??open?for?reading.??
Or?MAP_SHARED?was?requested?and?PROT_WRITE?is?set,?but?fd?is?not?open?
in?read/write?(O_RDWR)?mode.??Or?PROT_WRITE??is??set,??but??the?file?is?append-only.
/** 示例: 向共享內存寫入數據 **/ int main(int argc,char *argv[]) {int shmid = shm_open("/xyz", O_RDWR, 0);if (shmid == -1)err_exit("shm_open error");struct stat buf;if (fstat(shmid, &buf) == -1)err_exit("fstat error");Student *p = (Student *)mmap(NULL, buf.st_size,PROT_WRITE, MAP_SHARED, shmid, 0);if (p == MAP_FAILED)err_exit("mmap error");strcpy(p->name, "Hadoop");p->age = 5;munmap(p, buf.st_size);close(shmid); } /** 從共享內存讀出數據 **/ int main(int argc,char *argv[]) {int shmid = shm_open("/xyz", O_RDONLY, 0);if (shmid == -1)err_exit("shm_open error");struct stat buf;if (fstat(shmid, &buf) == -1)err_exit("fstat error");Student *p = (Student *)mmap(NULL, buf.st_size,PROT_READ, MAP_SHARED, shmid, 0);if (p == MAP_FAILED)err_exit("mmap error");cout << "name: " << p->name << ", age: " << p->age << endl;munmap(p, buf.st_size);close(shmid); }[附]
? ?-Posix共享內存默認創建在/dev/shm目錄下
? ?-可以使用od命令查看共享內存的內容
od?-c?/dev/shm/xyz
總結
以上是生活随笔為你收集整理的Linux IPC实践(10) --Posix共享内存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 发一个统计项目代码行数的Java代码
- 下一篇: HDR Tone Mapping