UNIX系统中的进程通信之共享内存

来源:互联网 发布:真融宝 靠谱吗 知乎 编辑:程序博客网 时间:2024/05/29 04:36

先来看下进程和线程把,面试中80%都会有的问题。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

而线程则是进程的实体,它是比进程更小的能独立运行的基本单位。也就是说线程必须运行在一个进程中,而一个进程则可以有多个线程。多个线程有共享进程中一定的数据,这样在多个线程中通信就变得很容易了,但是如果要在不同的进程间通信呢?

在UNIX下面主要有管道pipe,命名管道fifo,消息队列msgget,共享内存,读写文件等通信方式。

共享内存说简单点就是几个进程共同使用一块内存,但共享内存是最快的通信方式,应为他是直接读取内存的。他是把由一个进程创建的内存块直接映射到调用进程分配的地址。

每个系统的共享内存段在系统内核中也保持着一个内部的数据结构shmid_ds。此数据结构是在linux/shm.h中定义的,结构如下:

/* One shmid data structure for each shared memory segment in the system. */
struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment (bytes) */
time_t shm_atime; /* last attach time */
time_t shm_dtime; /* last detach time */
time_t shm_ctime; /* last change time */
unsigned short shm_cpid; /* pid of creator */
unsigned short shm_lpid; /* pid of last operator */
short shm_nattch; /* no. of current attaches */
/* the following are private */
unsigned short shm_npages; /* size of segment (pages) */
unsigned long *shm_pages; /* array of ptrs to frames -> SHMMAX */
struct vm_area_struct *attaches; /* descriptors for attaches */
};

可以 看到这个结构体中定义了很多有关共享内存有用的信息,其中shm_perm是ipc_perm的一个结构体,存放是内存段的存取权限,和其他的有关内存段创建者的信息。

其他的都可以从名称看出他的作用。

下面看下几个相关的函数:

shmget()这个是创建和获取一个共享内存的函数。函数原型int shmget(key_t key,int size,int shmflg);
第一个参数是关键值,一般都是在创建进程的时候得到的。第2个是块个大小。第3个是 命令参数,可以有下面的用法:

   IPC_CREAT如果系统内核中没有共享的内存段,则创建一个共享的内存段。
    IPC_EXCL当和IPC_CREAT一同使用时,如果共享内存段已经存在,则调用失败。
    当IPC_CREAT单独使用时,系统调用shmget()要么返回一个新创建的共享内存段的标识符,要么返回一个已经存在的共享内存段的关键字值。如果IPC_EXCL和IPC_CREAT一同使用,则要么系统调用新创建一个共享的内存段,要么返回一个错误值-1。IPC_EXCL单独使用没有意义。

如果成功,返回共享内存段标识符。

 

这样一个进程就可以得到一 块内存的通信标识符,然后就可以把这块内存放进调用进程的空间。

可以用shmat()函数,函数原型int shmat ( int shmid, char *shmaddr, int shmflg);其中第二个参数如果参数shmaddr的值为0,那么系统内核则试图找出一个没有映射的内存区域。我们推荐使用这种方法。你可以指定一个地址,但这通常是为了加快对硬件设备的存取,或者解决和其他程序的冲突。