LINUX下系统编程,多进程间数据共享,即共享变量

LINUX下系统编程,多进程间数据共享,即共享变量,第1张

共享内存相关的API怎么使用不难:

1. 首先调用shmget分配一个新的共享内存,这里你可以指定其大小,如果你要分配一个整形,那你可以将size参数设置成4,如果你要共享一个结构体那就将size参数设置成你的结构体大小, *** 作系统不关心你要共享什么,它只关心你要分配多少个字节的区间。而且实际上 *** 作系统会将你要求的大小按照内存页面的大小进行对齐,也就是说它可能实际上给你分配若干个页面的物理存储空间,只要这个空间能够容纳你所指定的大小就ok了。它的第三个参数是关于一些访问权限设置的,要讲起来太长,建议自己搜索一下,或者用man查查帮助。总之,调用完shmget以后系统会给你创建一段共享内存,然后返回给你一个shmid,也就是这个共享内存的标识,你可以理解为给它取了个名字。

2. 接着调用shmat将这段共享内存映射到你的进程的虚拟地址空间上。这个函数的第一个参数就是你之前调用shmget创建的共享内存的名字shmid;第二个参数是个指针,指向你的进程虚存空间中的某个地址,你可以通过传入一个确定的地址强行要求 *** 作系统将共享内存映射到你指定的虚存地址上(可能会失败,如果你指定的虚拟地址空间已经映射了别的物理存储空间),也可以通过传入0地址让系统给你选择一个合适的地址(它会通过返回值把地址返回给你)。第三个参数则允许你指定一些特殊的标志位,还是那句话,太复杂自己搜索一下看看,一般应用不需要用到。

至于例子嘛你可以看看下面这个链接:

http://baike.baidu.com/view/3025906.htm

另外,你要知道只用共享内存是不互斥的,你必须结合信号量一起使用才能防止互斥问题的出现。如果你共享的只是一个整形变量可能问题不大,因为对页面对齐的整形变量的读写都是原子 *** 作,但如果你共享的是个复杂的结构体就得小心了。

管道用于有学园关系的进程之间。

管道的pipe 系统调用实际上就是创建出来两个文件描述符。

当父进P1程创建出 fd[2] 时,子进程P2 会继承父进程的所有,所以也会得到pipe 的 2个 文件描述符。

所以毫无瓜葛的两个进程,一定不会访问到彼此的pipe。无法用管道进行通信。

管道一般是单工的。f[0]读,f[1]写

管道也可以适用于 兄弟进程(只要有血缘即可)。由于管道是单工的,当两个进程之间需要双向通信,则需要两跟管道。

执行

ctrl-c(2号信号) + SIGUSR1 信号 绑了一个新函数。则 ctrl-c 无效。

查看进程的信号

号信号被捕获。

将2号信号忽略掉

9号信号 kill 和19号信号 stop 不能乱搞,只能用缺省。

其它信号甚至段信号也都可以捕获。

改变程序的执行现场,修改PC指针,有些像goto,只不过返回非0值

运行结果

making segment fault

after segment fault

程序不会死。

如果不忽略 page fault

则会产生 core dump.

不停的给data 赋值,同时每隔1s会有信号进来,打印 data的值。

理论上打印出来的结果同时为0,同时为1

但并非如此,是 0,1,交替随机的。

signal 异步的,随时都可以进来,所以打印出来的结果,并不是我想要的。

信号对于应用程序来说,很像中断对于内核,都是访问临界区数据

信号被屏蔽,延后执行。

写多线程的程序时,不要以为只有线程之间有竞争,其实信号也会有竞争

system v 的IPC 年代有些久远。

有血缘关系的进程 key_t 都是相同的。

Key 是私有key IPV PRIVATE

可能用消息队列,可能用共享内存,可能用信号量进行通讯。

利用 _pathname 路径,约定好一条路径。和tcp/ip地址很像,来生成一个key_t key, 用msg_get shm_get 得到共享内存or 信号量。

int id 可以理解为文件描述符 fd。

其中Sys V 的共享内存 最为常用。

一定要检查路径,如果仅仅有2个进程,你没有创建路径,两者都是 -1(相当于大家约定好了),那当然能通信拉。但更多的进程出现,则会有问题。

一定要检查返回值

依然依靠key,但是api 实在是太挫了。P&V *** 作都是 semop. (posix 的 ipc跟为简洁)

POSIX 共享内存当然也需要一个名字,但并不是路径。

无论读进程还是写进程,都需要传入相同的名字。

如果是unbuntu 会在以下路径生成文件

其实 2和3 是1 的符号链接。 只要保证是一个就能互相通信

关键点,mmap 内存的属性修改为 private 后,产生写时copy,虚拟地址一样,但是物理地址已经不同了

当然 如果子进程修改了程序背景,执行了 exec,那么完全不一样了,直接修改了内存逻辑。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/7529733.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-06
下一篇2023-04-06

发表评论

登录后才能评论

评论列表(0条)

    保存