c语言shmdt函数,linux环境高级C语言知识整理:共享内存

四、共享内存

1.基本特点

(1) 两个或者更多进程,共享同一块由系统内核负责维护的内存区域,其地址空间通常被映射到堆和栈之间。

(2) 无需复制信息,最快的一种IPC机制。

(3) 需要考虑同步访问的问题。

(4) 内核为每个共享内存,维护一个shmid_ds结构体形式的共享内存对象。

2.常用函数

#include

(1) 创建/获取共享内存

int shmget (key_t key, size_t size, int shmflg);

A. 该函数以key参数为键值创建共享内存,或获取已有的共享内存。

B. size参数为共享内存的字节数, 建议取内存页字节数(4096)的整数倍。

若希望创建共享内存,则必需指定size参数。

若只为获取已有的共享内存,则size参数可取0。

C. shmflg取值:

0 - 获取,不存在即失败。

IPC_CREAT - 创建,不存在即创建,

已存在即获取,除非…

IPC_EXCL - 排斥,已存在即失败。

D. 成功返回共享内存标识,失败返回-1。

(2) 加载共享内存

void* shmat (int shmid, const void* shmaddr,int shmflg);

A. 将shmid参数所标识的共享内存,映射到调用进程的地址空间。

B. 可通过shmaddr参数人为指定映射地址,也可将该参数置NULL,由系统自动选择。

C. shmflg取值:

0 - 以读写方式使用共享内存。

SHM_RDONLY - 以只读方式使用共享内存。

SHM_RND - 只在shmaddr参数非NULL时起作用。

表示对该参数向下取内存页的整数倍,作为映射地址。

D. 成功返回映射地址,失败返回-1。

E. 内核将该共享内存的加载计数加1。

(3) 卸载共享内存

int shmdt (const void* shmaddr);

A. 从调用进程的地址空间中,取消由shmaddr参数所指向的,共享内存映射区域。

B. 成功返回0,失败返回-1。

C. 内核将该共享内存的加载计数减1。

(4) 销毁/控制共享内存

int shmctl (int shmid, int cmd, struct shmid_ds* buf);

A. cmd取值:

IPC_STAT

获取共享内存的属性,通过buf参数输出。

IPC_SET

设置共享内存的属性,通过buf参数输入,仅以下三个属性可设置:

shmid_ds::shm_perm.uid

shmid_ds::shm_perm.gid

shmid_ds::shm_perm.mode

IPC_RMID

标记删除共享内存。

并非真正删除共享内存,只是做一个删除标记,禁止其被继续加载,但已有加载依然保留。

只有当该共享内存的加载计数为0时,才真正被删除。

B. 成功返回0,失败返回-1。

struct shmid_ds

{

struct ipc_perm shm_perm; // 所有者及其权限

size_t shm_segsz; // 大小(以字节为单位)

time_t shm_atime; // 最后加载时间

time_t shm_dtime; // 最后卸载时间

time_t shm_ctime; // 最后改变时间

pid_t shm_cpid; // 创建进程PID

pid_t shm_lpid; // 最后加载/卸载进程PID

shmatt_t shm_nattch; // 当前加载计数

...

};

struct ipc_perm

{

key_t __key; // 键值

uid_t uid; // 有效属主ID

gid_t gid; // 有效属组ID

uid_t cuid; // 有效创建者ID

gid_t cgid; // 有效创建组ID

unsigned short mode; // 权限字

unsigned short __seq; // 序列号

};

编程模型

范例:wshm.c、rshm.c

wshm.c

#include

#include

#include

int main ()

{

printf ("创建共享内存...\n");

key_t key = ftok (".", 100);

if (key == -1)

{

perror ("ftok");

return -1;

}

int shmid = shmget (key, 4096, 0644 | IPC_CREAT | IPC_EXCL);

if (shmid == -1)

{

perror ("shmget");

return -1;

}

printf ("加载共享内存...\n");

void* shmaddr = shmat (shmid, NULL, 0);

if (shmaddr == (void*)-1)

{

perror ("shmat");

return -1;

}

printf ("写入共享内存...\n");

sprintf (shmaddr, "我是%u进程写入的数据。", getpid ());

printf ("按卸载共享内存(0x%08x/%d)...", key, shmid);

getchar ();

if (shmdt (shmaddr) == -1)

{

perror ("shmdt");

return -1;

}

printf ("按销毁共享内存(0x%08x/%d)...", key, shmid);

getchar ();

if (shmctl (shmid, IPC_RMID, NULL) == -1)

{

perror ("shmctl");

return -1;

}

printf ("大功告成!\n");

return 0;

}

rshm.c

#include

#include

#include

int shmstat (int shmid)

{

struct shmid_ds shm;

if (shmctl (shmid, IPC_STAT, &shm) == -1)

{

perror ("shmctl");

return -1;

}

printf ("------------------------------------------------\n");

printf (" 共享内存信息\n");

printf ("----+----------------+--------------------------\n");

printf (" 所 | 键值 | 0x%08x\n", shm.shm_perm.__key);

printf (" 有 | 有效属主ID | %u\n", shm.shm_perm.uid);

printf (" 者 | 有效属组ID | %u\n", shm.shm_perm.gid);

printf (" 及 | 有效创建者ID | %u\n", shm.shm_perm.cuid);

printf (" 其 | 有效创建组ID | %u\n", shm.shm_perm.cgid);

printf (" 权 | 权限字 | %#o\n", shm.shm_perm.mode);

printf (" 限 | 序列号 | %u\n", shm.shm_perm.__seq);

printf ("----+----------------+--------------------------\n");

printf (" 大小(字节) | %u\n", shm.shm_segsz);

printf (" 最后加载时间 | %s", ctime (&shm.shm_atime));

printf (" 最后卸载时间 | %s", ctime (&shm.shm_dtime));

printf (" 最后改变时间 | %s", ctime (&shm.shm_ctime));

printf (" 创建进程ID | %u\n", shm.shm_cpid);

printf (" 最后加载/卸载进程ID | %u\n", shm.shm_lpid);

printf (" 当前加载计数 | %ld\n", shm.shm_nattch);

printf ("---------------------+--------------------------\n");

return 0;

}

int shmset (int shmid)

{

struct shmid_ds shm;

if (shmctl (shmid, IPC_STAT, &shm) == -1)

{

perror ("shmctl");

return -1;

}

shm.shm_perm.mode = 0600;

shm.shm_segsz = 8192;

if (shmctl (shmid, IPC_SET, &shm) == -1)

{

perror ("shmctl");

return -1;

}

return 0;

}

int main ()

{

printf ("获取共享内存...\n");

key_t key = ftok (".", 100);

if (key == -1)

{

perror ("ftok");

return -1;

}

int shmid = shmget (key, 0, 0);

if (shmid == -1)

{

perror ("shmget");

return -1;

}

printf ("加载共享内存...\n");

void* shmaddr = shmat (shmid, NULL, 0);

if (shmaddr == (void*)-1)

{

perror ("shmat");

return -1;

}

shmstat (shmid);

printf ("读取共享内存...\n");

printf ("共享内存(0x%08x/%d):%s\n", key, shmid, (char*)shmaddr);

printf ("卸载共享内存...\n");

if (shmdt (shmaddr) == -1)

{

perror ("shmdt");

return -1;

}

shmstat (shmid);

printf ("设置共享内存...\n");

shmset (shmid);

shmstat (shmid);

printf ("大功告成!\n");

return 0;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值