知道ip域名如何进入网站,网站的架设,3d效果图设计制作软件,网站开发参考文献格式文章目录 进程间通信1.system V共享内存1.1共享内存原理1.2共享内存数据结构1.3共享内存函数 2.system V消息队列2.1消息队列原理 3.system V信号量3.1信号量原理3.2进程互斥 4.共享内存的使用示例 进程间通信
1.system V共享内存
1.1共享内存原理 共享内存区是最快的IPC形式… 文章目录 进程间通信1.system V共享内存1.1共享内存原理1.2共享内存数据结构1.3共享内存函数 2.system V消息队列2.1消息队列原理 3.system V信号量3.1信号量原理3.2进程互斥 4.共享内存的使用示例 进程间通信
1.system V共享内存
1.1共享内存原理 共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间这些进程间数据传递不再涉及到内核换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。 本质还是先让不同的进程看到同一份资源。 所以共享内存是Unix下的多进程之间的通信方法允许多个进程访问同一个内存空间是在多个进程之间共享和传递数据最高效的方式。共享内存本质上是一块物理内存多个进程通过将同一块物理内存都映射到自己的虚拟地址空间通过自己的虚拟地址进行访问实现数据间的共享。 如果某个进程修改了共享内存中的数据其它的进程读到的数据也将会改变。但是需要注意的是共享内存并未提供锁机制也就是说在某一个进程对共享内存的进行读写的时候不会阻止其它的进程对它的读写。如果要对共享内存的读/写加锁可以使用信号灯。 1.2共享内存数据结构
struct shmid_ds {struct ipc_perm shm_perm; /* operation perms */int shm_segsz; /* size of segment (bytes) */__kernel_time_t shm_atime; /* last attach time */__kernel_time_t shm_dtime; /* last detach time */__kernel_time_t shm_ctime; /* last change time */__kernel_ipc_pid_t shm_cpid; /* pid of creator */__kernel_ipc_pid_t shm_lpid; /* pid of last operator */unsigned short shm_nattch; /* no. of current attaches */unsigned short shm_unused; /* compatibility */void *shm_unused2; /* ditto - used by DIPC */void *shm_unused3; /* unused */
};Linux的共享内存数据结构是struct shmid_ds它定义了共享内存的一些重要属性。这个结构体包括以下字段 struct ipc_perm shm_perm这个字段包含了操作权限如读、写和执行等。 int shm_segsz这个字段表示共享内存段的字节大小。 __kernel_time_t shm_atime这个字段表示最后一次附加的时间。 __kernel_time_t shm_dtime这个字段表示最后一次分离的时间。 __kernel_time_t shm_ctime这个字段表示最后一次更改的时间。 __kernel_ipc_pid_t shm_cpid这个字段表示创建者的进程ID。 __kernel_ipc_pid_t shm_lpid这个字段表示最后一次操作共享内存的进程ID。 unsigned short shm_nattch这个字段表示当前附加到共享内存的进程数。 unsigned short shm_unused这个字段是用于兼容的目前未使用。 这个结构体主要用于在Linux内核中描述POSIX共享内存即System V共享内存。在用户空间中通常使用的是shmget(), shmat(), shmdat()等系统调用与内核的POSIX共享内存交互。 1.3共享内存函数 shmget函数 功能用来创建共享内存 原型: int shmget(key_t key, size_t size, int shmflg); 参数: key:这个共享内存段名字 size:共享内存大小 shmflg:由九个权限标志构成它们的用法和创建文件时使用的mode模式标志是一样的 返回值成功返回一个非负整数即该共享内存段的标识码失败返回-1。 shmat函数 功能将共享内存段连接到进程地址空间 原型void *shmat(int shmid, const void *shmaddr, int shmflg); 参数 shmid: 共享内存标识 shmaddr:指定连接的地址 shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY 返回值成功返回一个指针指向共享内存第一个节失败返回-1 注意 shmaddr为NULL核心自动选择一个地址 shmaddr不为NULL且shmflg无SHM_RND标记则以shmaddr为连接地址。 shmaddr不为NULL且shmflg设置了SHM_RND标记则连接的地址会自动向下调整为SHMLBA的整数倍。公式shmaddr - (shmaddr % SHMLBA) shmflgSHM_RDONLY表示连接操作用来只读共享内存 shmdt函数 功能将共享内存段与当前进程脱离 原型int shmdt(const void *shmaddr); 参数 shmaddr: 由shmat所返回的指针 返回值成功返回0失败返回-1 注意将共享内存段与当前进程脱离不等于删除共享内存段 shmctl函数 功能用于控制共享内存 原型int shmctl(int shmid, int cmd, struct shmid_ds *buf); 参数 shmid:由shmget返回的共享内存标识码 cmd:将要采取的动作有三个可取值 buf:指向一个保存着共享内存的模式状态和访问权限的数据结构 返回值成功返回0失败返回-1 2.system V消息队列 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法。 每个数据块都被认为是有一个类型接收者进程接收的数据块可以有不同的类型值。 特性方面IPC资源必须删除否则不会自动清除 除非重启所以system V IPC资源的生命周期随内核。 2.1消息队列原理 System V消息队列的原理是基于消息块的数据结构可以在进程间传递数据。每个消息块都有一个类型和信息两部分构成。两个进程可以通过System V消息队列互相发送和接收消息。发送消息时进程将数据块添加到消息队列的队尾接收消息时进程从消息队列的队头获取数据块。 需要注意的是System V消息队列的资源必须自行删除否则不会自动清除因为System V IPC资源的生命周期是随内核的。同时消息队列数据结构也可能会存在大量的消息队列系统也必须为消息队列维护相关的内核数据结构。
3.system V信号量
3.1信号量原理 System V信号量集也称为信号量的原理是基于一种数据操作锁相当于资源计数器用于同步和协调多个进程之间的数据交换。它自身不具备数据交换功能。 信号量的工作原理基于两种原子性操作waitp和signalv。 当一个进程进行waitp操作时如果信号量的值大于0则该进程可以继续执行并使用一个资源将信号量的值减1如果信号量的值为0则该进程会被阻塞直到其他进程释放资源使信号量的值大于0为止。当一个进程进行signalv操作时如果信号量的值小于等于0则该进程可以继续执行并使用一个资源将信号量的值加1如果信号量的值大于0则进程不会得到资源因为已有其他进程在使用资源。 信号量的作用是维护资源的互斥和多进程的同步访问以确保在一个时间点只有一个进程可以访问共享资源从而避免了多个进程同时访问共享资源而引起的竞争条件。 同时信号量也可以用于控制多个进程之间的同步和通信。
3.2进程互斥 由于各进程要求共享资源而且有些资源需要互斥使用因此各进程间竞争使用这些资源进程的这种关系为进程的互斥。 系统中某些资源一次只允许一个进程使用称这样的资源为临界资源或互斥资源。 在进程中涉及到互斥资源的程序段叫临界区。 特性方面IPC资源必须删除否则不会自动清除除非重启所以system V IPC资源的生命周期随内核。
4.共享内存的使用示例
makefile
.PHONY:all
all:server client
client:client.c comm.cgcc -o $ $^
server:server.c comm.cgcc -o $ $^.PHONY:clean
clean:rm -f client servercomm.h
#include stdio.h
#include sys/types.h
#include sys/ipc.h
#include sys/shm.h#define PATHNAME .
#define PROJ_ID 0x6666int createShm(int size);
int destroyShm(int shmid);
int getShm(int size);#endifcomm.c
static int commShm(int size, int flags)
{key_t _key ftok(PATHNAME, PROJ_ID);if(_key 0){perror(ftok);return -1;}int shmid 0;if( (shmid shmget(_key, size, flags)) 0){perror(shmget);return -2;}return shmid;
}int destroyShm(int shmid)
{if(shmctl(shmid, IPC_RMID, NULL) 0){perror(shmctl);return -1;}return 0;
}int createShm(int size)
{return commShm(size, IPC_CREAT|IPC_EXCL|0666);
}int getShm(int size)
{return commShm(size, IPC_CREAT);
}server.c
#include comm.h
int main()
{int shmid createShm(4096);char *addr shmat(shmid, NULL, 0);sleep(2);int i 0;while(i26){printf(client# %s\n, addr);sleep(1);}shmdt(addr);sleep(2);destroyShm(shmid);return 0;
}client.c
#include comm.h
int main()
{int shmid getShm(4096);sleep(1);char *addr shmat(shmid, NULL, 0);sleep(2);int i 0;while(i26){addr[i] Ai;i;addr[i] 0;sleep(1);}shmdt(addr);sleep(2);return 0;
}