(整理)并发编程之一:多进程
(引)并发网络编程学习之路(三):多线程与进线池

(转)并发网络编程学习之路(二):多进程与进程池(续)

孔令春 posted @ 2009年10月19日 23:33 in 网络安全 with tags 共享内存 进程池 , 5459 阅读

转自:http://book.51cto.com/art/200903/114895.htm

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

        下面实例演示了使用shmget函数创建一块共享内存。程序中在调用shmget函数时指定key参数值IPC_PRIVATE,这个参数的意义是创建一个机关报的共享内存区,当创建成功后使用shell命令ipcs来显示目前系统下共享内存的状态。命令参数-m为显示共享内存的状态。

#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

对共享内存段解锁,此命令只能由超级用户请求

 

 

       使用函数shmat将一个存在的共享内存段连接到本进程空间,其函数原型如下:

 

#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下多进程设计模式

              一个简单的进程池实例

 

Avatar_small
BBMP property tax 说:
2022年8月01日 21:35

BBMP celebrated as Bruhat Bengaluru Mahanagara Palike. It is a civic amenity of the greater Bangalore metropolitan area. The administrative body of the Greater Bangalore area fully managed under BBMP which ruled by municipal commissioner.The properties under this BBMP zone are termed to have a different slab of the Property Tax for commercial or private under BBMP, BBMP property tax does have a valid tax amount due to the growth in their surroundings. The amount for the BBMP tax calculated by municipal authority. This may checked from retrieving your details from the official portal. Citizens can also use the tax calculator form the BBMP Portal. You may calculate the amount that is to pay as per your Tax calculation.

Avatar_small
Uttarakhand Board 6t 说:
2022年8月16日 00:32

Uttarakhand Board Model Paper 2023 Class 6 Pdf Download with Answers for English Medium, Hindi Medium, Urdu Medium & Students for Small Answers, Long Answer, Very Long Answer Questions, and Essay Type Questions to Term1 & Term2 Exams

Avatar_small
Jharkhand Board Ques 说:
2022年8月31日 23:54

Jharkhand Board Model Paper 2023 Class 3 Pdf Download with Answers for English Medium, Hindi Medium, Urdu Medium & Students for Small Answers, Long Answer, Very Long Answer Questions, and Essay Type Questions to Term1 & Term2 Exams at official website. Jharkhand Board Question Paper Class 3 New Exam Scheme or Question Pattern for Sammittive Assignment Exams (SA1 & SA2): Very Long Answer (VLA), Long Answer (LA), Small Answer (SA), Very Small Answer (VSA), Single Answer, Multiple Choice and etc.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter