找设计师的网站,网站转移空间备案是不是就没有了,张家口网站建设电话,动态h5网站开发管道 System V 共享内存 System V IPC 接口介绍
由于进程地址空间的存在#xff0c;所以进程间有具有独立性#xff0c;一个进程看不到另一个进程的数据。那么如果我们想让进程间通信#xff0c;就必须先让它们先看到同一份资源。常见的进程间通信的方法有管道#xff0c;… 管道 System V 共享内存 System V IPC 接口介绍
由于进程地址空间的存在所以进程间有具有独立性一个进程看不到另一个进程的数据。那么如果我们想让进程间通信就必须先让它们先看到同一份资源。常见的进程间通信的方法有管道System V IPC POSIX IPC。管道是最古老的一种通信手段System V POSIX 是用于进程间通信的标准。
一.管道
管道的本质是文件让两个进程看到同一份文件即指向同一个struct file 结构体就能让两个进程看到同一份资源之后就可以开始正常通信了。
1.1 匿名管道
匿名管道就是利用系统调用在程序内创建一个内存级文件(只有struct file结构体)通过父子进程间的继承关系来看到同一份文件。接口
功能用读写方式打开匿名文件pipefd[0] 表示读方式打开pipefd[1] 表示写方式打开
当父进程创建子进程时子进程会复制大部分父进程的task_struct。故此父进程打开的文件子进程也能看到。如图 由于管道是单向通信所以我们应该关闭不需要的fd。如果我们想让父进程读子进程写则需关闭父进程写端pipefd[1],子进程读端pipefd[0]。之后父进程就可以正常通信了。代码示例如下
int main()
{int pipefd[2];int n pipe(pipefd);assert(n ! -1);pid_t id fork();if (id 0){// 子进程close(pipefd[0]);// 通信代码。。。//通信完毕关闭文件描述符close(pipefd[1]);exit(0);}// 父进程close(pipefd[1]);// 通信代码。。。。waitpid(id, nullptr, 0);close(pipefd[0]);return 0;
}特性
匿名管道是一种单向通信方式是半双工的一种特殊情况。匿名管道用于具有血缘关系的进程之间通信比如父子兄弟由于匿名管道是文件所以生命周期随进程面向字节流当写入的字节数小于PIPE_BUFF(4096)时保证其原子性由于匿名管道是通过系统调用写入和读出数据所以自带保护机制同步 当写端退出读端读完数据后read系统调用返回0当读端退出写端立即退出os向写端发送SIGPIPE信号当缓冲区空时读端阻塞等待写端写入数据当缓冲区数据满时写端阻塞等待读端读取数据 1.2 命名管道
匿名管道主要用于具有血缘关系的进程如果想让两个没有关系的进程通信就需要用到命名管道命名管道具有Inode节点但是没有Data Blocks不会将数据刷新到磁盘它只用于进程间通信。创建命名管道有两种方式1.命令行mkfifo 指令 2.函数接口mkfifo接口
命令行mkfifo 函数接口mkfifo pathname在哪个路径下创建mode文件的起始权限
需要通信的多个进程中只要有一个进程创建了命名管道然后其他进程只需要知道路径就能满足多个进程看到同一份资源。代码下面构造一个客户端与服务端的代码示例。由服务器端创建命名管道服务区读客户端写
#define PATHNAME ./fifo
// server.c int main()
{mkfifo(PATHNAME, 0666);int fd open(PATHNAME, O_RDONLY);// 调用read函数进行读取数据通信close(fd);// 删除管道文件unlink(PATHNAME);return 0;
}//
// client.c int main()
{int fd open(PATHNAME, O_WRONLY);// 调用write函数向管道写入数据close(fd);return 0;
}二.System V 共享内存
进程间通信除了管道还可以调用系统接口在内存中创建一块共享空间并且将这块共享空间映射到程序地址空间中关联此时进程就可以读写这块空间。共享内存在操作系统内可能有很多为了便于管理需要有一个结构体。类似于进程等于内核数据结构代码共享内存内核数据结构空间。ipcs -m 可以查看系统内部的共享内存ipcrm -m shmid 可以根据shmid删除共享内存
1.接口介绍
创建共享内存shmget key一个整数多个进程只要保证调用shmget时传递相同的key就可以保证打开同一个共享内存。获取key可以用ftok函数其中参数是自己设定的size共享内存的实际可用大小。操作系统分配是以4KB为单位的。shmflg位图结构体常用的宏IPC_CREAT IPC_EXCL也可以设置共享内存的权限返回值返回一个shmid值shmid与key的关系。shmid和key的关系类似于文件inode编号和fd的关系。key类似于inode编号shmid类似于fd 2. 进程与共享内存关联与取消关联 shmat进程与共享内存关联 shmaddr一般设置为空shmflg一般设置为0返回值返回共享内存在虚拟空间中的地址 shmdt 根据虚拟地址将共享内存与进程取消关联 删除共享内存 shmctl有许多功能例如查看共享内存结构体的属性删除共享内存等等我们重点用这个接口删除共享内存将cmd参数设置为IPC_RMID ,即可删除对应的共享内存
2.代码示例
三个文件一个头文件放函数定义一个客户端文件一个服务端文件服务端创建共享内存和删除共享内存。
#include iostream
#include sys/ipc.h
#include sys/shm.h
#include sys/types.h
#include sys/stat.h
#include string
#include cstring
#include unistd.husing namespace std;//int shmget(key_t key, size_t size, int shmflg);
//key_t ftok(const char *pathname, int proj_id);const string pathname .;
const int proj_id 0432;
const size_t shmSize 4096;key_t getKey(const string pathname, int proj_id)
{return ftok(pathname.c_str(), proj_id);
}// 当shmflg IPC_CREAT | IPC_EXCL 表明创建一个共享内存,
// 如果不存在则创建存在则报错
int shmHelper(int shmflg)
{key_t key getKey(pathname, proj_id);int shmid shmget(key, shmSize, shmflg);cout shmid endl;if (shmid -1){cerr errno : strerror(errno) endl;exit(1);}return shmid;
}int createShm()
{umask(0);return shmHelper(IPC_CREAT | IPC_EXCL|0666); // 不存在则创建存在则返回shmid
}int getShm()
{return shmHelper(IPC_CREAT);// 不存在则创建存在则失败返回
}char* attchShm(int shmid)
{// 用法和malloc差不多char* begin (char*)shmat(shmid, nullptr, 0);if (begin (void*)-1){cerr errno : strerror(errno) endl;exit(1);}return begin;
}void detachShm(char* begin)
{int n shmdt(begin);if (n -1){cerr errno : strerror(errno) endl;exit(1);}
}void destroyShm(int shmid)
{int n shmctl(shmid, IPC_RMID, nullptr);if (n -1){cerr errno : strerror(errno) endl;exit(1);}
}
#includecommon.hppint main()
{// 1. 创建共享内存int shmid createShm();// 2.与进程关联char* begin attchShm(shmid);//中间就是通信部分int i 0;while (true){sleep(3);cout begin[i] endl;i % 25;sleep(1);}// 3.去关联detachShm(begin);// 4. 销毁共享内存destroyShm(shmid);return 0;
#includecommon.hppint main()
{// 1. 获取共享内存int shmid getShm(); // 2.与进程关联char* begin attchShm(shmid);//通信部分// 共享内存没有保护机制所以int i 0;while (true){begin[i] ai;i % 25;sleep(1);}// 3.去关联detachShm(begin);return 0; 3.共享内存的特点
大小是以4KB为单位的比如在shmget中设置size为4087它会向上对奇到2KB速度在众多通信方式中是最快因为它是直接访问内存不用经过函数调用没有保护机制同步互斥。因为不经过系统调用所以保护机制需要由用户设置
三.System V IPC接口介绍
System V IPC 有三种通信方式共享内存消息队列信号量。由于System V 定义的是一套标准所以它们的接口都很相似。命令行中可以用ipcs查看这三种通信方式的属性。也可以用 ipcs -q 查看消息队列ipcs -s 查看信号量ipcs -m 查看共享内存。删除命令ipcrm -m/-s/-q下面初步了解一下接口知道它们的相似性。
1.消息队列
创建消息队列msgget 发送/接受消息msgsnd-发送msgrcv-接收
其中msgp需要用户自定义
删除消息队列msgctl(msqid, IPC_RMID, nullptr) 2.信号量
信号量信号灯可以将它看作一个计数器表明可用资源的数量。信号量可与共享内存协同工作每一次申请空间资源时信号量-1当信号量为0时申请资源的进程挂起。当释放空间资源时信号量1。
创建semget nsems一次创建多个信号量
操作加1减1。semop nsops指明需要对哪个信号量做操作默认为0sops设置操作方式
当sem_op 为-1时表明信号量做-1操作当sem_op为1时表明信号量做1操作
删除信号量