并发网络编程学习之路(二):多进程与进程池(续)
2015-08-10 20:57
429 查看
转自:http://book.51cto.com/art/200903/114895.htm
3.3共享内存
3.3.1共享内存的概念
在系统内核为一个进程分配内存地址进,通过分布机制可以让一个进程的物理地址不连续,同时也可以让一段内存同时分配给不同的进程。共享机制就是通过该原理来实现的,共享内存机制只是提供数据的传送,如何控制服务器端和客户端的读写操作互斥,这就需要一些其他的辅助工具,例如记录锁。
对于每一个共享存储段,内核分为其维护一个shmid_ds类型的结构体(shmid_ds结构定义在头文件<sys/shm.h>中)。shmid_ds结构体定义如下:
结构体shmid_ds会根据不同的系统内核版本而略有不同,并且在不同的系统中会对共享存储段的大小有限制,在应用时请查询相应系统手册。
3.3.2 共享内存的创建
共享内存是存在于内核级别的一种资源,在shell中可以使用ipcs命令来查看当前系统IPC中的状态,在文件系统/proc目录下有对其描述的相应文件。函数shmget可以创建或打开一块共享内存区。函数原型如下:
函数中参数key用来变换成一个标识符,而且每一个IPC对象与一个Key相对应。当新建一个共享内存段时,size参数为要请求的内存长度(以字节为单位)。
注意:内核是以页为单位分配内存,当size参数的值不是系统内存页长的整数倍时,系统会分配给进程最小的可以满足size长的页数,但是最后一页的剩余部分是不可用的。
当打开一个内存段时,参数size的值为0。参数flag中的相应权限位初始化ipc_perm结构体中的mode域。同时参数flag是函数行为参数,它指定一些当函数遇到阻塞或其他情况时应做出的反应。shmid_ds结构初始化如下:
下面实例演示了使用shmget函数创建一块共享内存。程序中在调用shmget函数时指定key参数值IPC_PRIVATE,这个参数的意义是创建一个机关报的共享内存区,当创建成功后使用shell命令ipcs来显示目前系统下共享内存的状态。命令参数-m为显示共享内存的状态。
?
3.3.3共享内存的操作
由于共享内存这一特殊资源类型,使它不同于普通的文件,因此,系统需要为其提供专有的操作函数,而这无疑增加了程序员开发的难度(需要记忆额外的专有函数)。使用函数shmctl可以对共享内存进行多种操作,其函数原型如下:
函数中参数shm_id为所要操作的共享内存的标识符,struct shmid_ds型指针参数buf的作用与参数cmd的值相关,参数cmd指明了所要进行的操作,其解释如下:
表14-5 shmctl函数中参数 cmd详解
使用函数shmat将一个存在的共享内存段连接到本进程空间,其函数原型如下:
函数中参数shm_id指定要引入的共享内存,参数addr与flag组合说明要引入的地址值,通常只有2种用法:addr为0 ,表明让内核来决定第1个可以引入的位置;非零,并且 flag中指定SHM_RND,则此段引入到addr所指向的位置(此操作不推荐使用,因为不会只对一种硬件上运行应用程序,为了程序的可移植性推荐使用前一种方法)。在flag参数中可以指定要引入的方式(读写方式指定)。
说明:函数成功执行返回值为实际引入的地址,失败返回-1。shmat函数成功执行会将shm_id段的shmid_ds结构的shm_nattch计数器的值加1。
当对共享内存段操作结束时,应调用shmdt函数,作用是将指定的共享内存段从当前进程空间中脱离出去。函数原型如下:
参数addr是调用shmat函数的返回值,函数执行成功返回0,并将该共享内存的shmid_ds结构的shm_nattch计数器减1,失败返回-1。
下面实例演示了操作共享内存段的流程。程序的开始部分检测用户是否有输入,如出错则打印该命令的使用帮助。接下来从命令行读取将要引入的共享内存ID,使用shmat函数引入该共享内存,并在分离内存之前睡眠3秒以方便查看系统IPC状态:
?
3.3.4共享内存使用注意事项
共享内存相比其他几种方式有着更方便的数据控制能力,数据在读写过程中会更透明。当成功导入一块共享内存后,它只是相当于一个字符串指针来指向一块内存, 有进程下用户可以随意的访问。缺点是数据写入进程或数据读出进程中,需要附加的数据结构控制,在共享内存段中都是以字符串的默认结束符为一条信息的的结尾。每个进程在读写时都遵守这个规则,就不会破坏数据的完整性。
二、进程池
由于网上进程池资料不多,只找到两个,本人也没有弄明白,现将链接贴出,留作备份:
Linux下多进程设计模式
一个简单的进程池实例
3.3共享内存
3.3.1共享内存的概念
在系统内核为一个进程分配内存地址进,通过分布机制可以让一个进程的物理地址不连续,同时也可以让一段内存同时分配给不同的进程。共享机制就是通过该原理来实现的,共享内存机制只是提供数据的传送,如何控制服务器端和客户端的读写操作互斥,这就需要一些其他的辅助工具,例如记录锁。
对于每一个共享存储段,内核分为其维护一个shmid_ds类型的结构体(shmid_ds结构定义在头文件<sys/shm.h>中)。shmid_ds结构体定义如下:
struct shmid_ds{ struct ipc_perm shm_pem; size_t shm_segsz; pid_T shm_lpid; pid_t shm_cpid; shmatt_t shm_nattch; time_t shm_atime; time_t shm_dtime; time_t shm_ctime; .... };
结构体shmid_ds会根据不同的系统内核版本而略有不同,并且在不同的系统中会对共享存储段的大小有限制,在应用时请查询相应系统手册。
3.3.2 共享内存的创建
共享内存是存在于内核级别的一种资源,在shell中可以使用ipcs命令来查看当前系统IPC中的状态,在文件系统/proc目录下有对其描述的相应文件。函数shmget可以创建或打开一块共享内存区。函数原型如下:
#include <sys/shm.h> int shmget(key_t key, size_t size, int flag);
函数中参数key用来变换成一个标识符,而且每一个IPC对象与一个Key相对应。当新建一个共享内存段时,size参数为要请求的内存长度(以字节为单位)。
注意:内核是以页为单位分配内存,当size参数的值不是系统内存页长的整数倍时,系统会分配给进程最小的可以满足size长的页数,但是最后一页的剩余部分是不可用的。
当打开一个内存段时,参数size的值为0。参数flag中的相应权限位初始化ipc_perm结构体中的mode域。同时参数flag是函数行为参数,它指定一些当函数遇到阻塞或其他情况时应做出的反应。shmid_ds结构初始化如下:
shmid_ds结构数据 | 初 值 | shmid_ds结构数据 | 初 值 |
shm_lpid | 0 | shm_dtime | 0 |
shm_nattach | 0 | shm_ctime | 系统当前值 |
shm_atime | 0 | shm_segsz | 参数 size |
?
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <stdio.h> #define BUFSZ 4096 int main ( void ) { int shm_id; /*共享内存标识符*/ shm_id=shmget(IPC_PRIVATE, BUFSZ, 0666 ) ; if (shm_id < 0 ) { /*创建共享内存*/ perror( "shmget" ) ; exit ( 1 ); } printf ( "successfully created segment : %d \n", shm_id ) ; system( "ipcs -m"); /*调用ipcs命令查看IPC*/ exit( 0 ); }
3.3.3共享内存的操作
由于共享内存这一特殊资源类型,使它不同于普通的文件,因此,系统需要为其提供专有的操作函数,而这无疑增加了程序员开发的难度(需要记忆额外的专有函数)。使用函数shmctl可以对共享内存进行多种操作,其函数原型如下:
#include <sys/shm.h> int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
函数中参数shm_id为所要操作的共享内存的标识符,struct shmid_ds型指针参数buf的作用与参数cmd的值相关,参数cmd指明了所要进行的操作,其解释如下:
表14-5 shmctl函数中参数 cmd详解
cmd的值 | 意 义 |
IPC_STAT | 取shm_id所指向内存共享段的shmid_ds 结构,对参数buf指向的结构赋值 |
IPC_SET | 使用buf指向的结构对sh_mid段的相关结 构赋值,只对以下几个域有作用,shm_perm. uid shm_perm.gid以及shm_perm.mode 注意此命令只有具备以下条件的进程才可以请求: 1.进程的用户ID等于shm_perm.cuid或者 等于shm_perm.uid 2.超级用户特权进程 |
IPC_RMID | 删除shm_id所指向的共享内存段,只有当 shmid_ds结构的shm_nattch域为零时,才 会真正执行删除命令,否则不会删除该段 注意此命令的请求规则与IPC_SET命令相同 |
SHM_LOCK | 锁定共享内存段在内存,此命令只能由超级用户请求 |
SHM_UNLOCK | 对共享内存段解锁,此命令只能由超级用户请求 |
#include <sys/shm.h> void *shmat(int shm_id, const void *add, int flag);
函数中参数shm_id指定要引入的共享内存,参数addr与flag组合说明要引入的地址值,通常只有2种用法:addr为0 ,表明让内核来决定第1个可以引入的位置;非零,并且 flag中指定SHM_RND,则此段引入到addr所指向的位置(此操作不推荐使用,因为不会只对一种硬件上运行应用程序,为了程序的可移植性推荐使用前一种方法)。在flag参数中可以指定要引入的方式(读写方式指定)。
说明:函数成功执行返回值为实际引入的地址,失败返回-1。shmat函数成功执行会将shm_id段的shmid_ds结构的shm_nattch计数器的值加1。
当对共享内存段操作结束时,应调用shmdt函数,作用是将指定的共享内存段从当前进程空间中脱离出去。函数原型如下:
#include <sys/shm.h> int shmdt(void *addr);
参数addr是调用shmat函数的返回值,函数执行成功返回0,并将该共享内存的shmid_ds结构的shm_nattch计数器减1,失败返回-1。
下面实例演示了操作共享内存段的流程。程序的开始部分检测用户是否有输入,如出错则打印该命令的使用帮助。接下来从命令行读取将要引入的共享内存ID,使用shmat函数引入该共享内存,并在分离内存之前睡眠3秒以方便查看系统IPC状态:
?
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <stdio.h> int main ( int argc, char *argv[] ) { int shm_id ; char * shm_buf; if ( argc != 2 ){ /* 命令行参数错误 */ printf ( "USAGE: atshm <identifier>" ); /*打印帮助消息*/ exit (1 ); } shm_id = atoi(argv[1]); /*得到要引入的共享内存段*/ /*引入共享内存段,由内核选择要引入的位置*/ if ( (shm_buf = shmat( shm_id, 0, 0)) < (char *) 0 ){ perror ( "shmat" ); exit (1); } printf ( " segment attached at %p\n", shm_buf ); /*输出导入的位置*/ system("ipcs -m"); sleep(3); /* 休眠 */ if ( (shmdt(shm_buf)) < 0 ) { /*与导入的共享内存段分离*/ perror ( "shmdt"); exit(1); } printf ( "segment detached \n" ); system ( "ipcs -m " ); /*再次查看系统IPC状态*/ exit ( 0 ); }
3.3.4共享内存使用注意事项
共享内存相比其他几种方式有着更方便的数据控制能力,数据在读写过程中会更透明。当成功导入一块共享内存后,它只是相当于一个字符串指针来指向一块内存, 有进程下用户可以随意的访问。缺点是数据写入进程或数据读出进程中,需要附加的数据结构控制,在共享内存段中都是以字符串的默认结束符为一条信息的的结尾。每个进程在读写时都遵守这个规则,就不会破坏数据的完整性。
二、进程池
由于网上进程池资料不多,只找到两个,本人也没有弄明白,现将链接贴出,留作备份:
Linux下多进程设计模式
一个简单的进程池实例
相关文章推荐
- 我的Android进阶之旅------>HTTP Content-type 对照表
- 简单区分Vmware的三种网络连接模式(bridged、NAT、host-only)
- NS3网络仿真(10): 解析以太网帧
- HttpSessionListener实现session定时扫描仪
- NS3网络仿真(9): 构建以太网帧
- 高性能网络编程5--IO复用与并发编程
- 高性能网络编程4--TCP连接的关闭
- 高性能网络编程3----TCP消息的接收
- 高性能网络编程2----TCP消息的发送
- 高性能网络编程1----accept建立连接
- HttpSessionListener接口监听网站在线人数
- JCIFS简介and利用JCIFS网络文件共享实现上传下载
- 黑马程序员-网络编程(二)
- 计算机网络--TCP协议中的三次握手和四次挥手(图解)
- 多线程从网络下载文件
- Apache HTTP Server .htaccess文件详解
- http和https的区别
- [网络流] 二分图匹配
- java基础第十讲——数据库、单例设计模式、服务器、项目(数据库—服务器—网络)
- BaseHTTPServer构建基本服务器