当前位置: 首页 > news >正文

网站开发pdf网站的友情链接是什么意思

网站开发pdf,网站的友情链接是什么意思,内蒙古建设厅网站首页,做棋牌游戏网站进程间通信#xff0c;顾名思义#xff0c;就是进程与进程之间互通信交流#xff0c;OS保证了各进程之间相互独立#xff0c;但这不意味着进程与进程之间就互相隔离开#xff0c;在不少的情况下#xff0c;进程之间需要相互配合共同完成某项6任务#xff0c;这就要求各进… 进程间通信顾名思义就是进程与进程之间互通信交流OS保证了各进程之间相互独立但这不意味着进程与进程之间就互相隔离开在不少的情况下进程之间需要相互配合共同完成某项6任务这就要求各进程之间能够互相交流此篇博客就是讲述进程之间交流的方法和原理笔者尽可能将大家会产生疑惑的点写出来大家可以收藏慢慢观看笔者并非大佬文章有错误在所难免望读者指出共同讨论 目录 进程间通信的目的 如何实现进程间通信 管道通信 匿名管道通信  命名管道通信 命名管道与匿名管道之间的区别 匿名管道的打开规则 共享内存  共享内存的优缺点 消息队列  信号量 进程间通信的目的 进程间通信的目的和原因有如下几个点 数据传输一个进程需要将它的数据发送给另一个进程 资源共享多个进程之间共享同样的资源 通知事件一个进程需要向另一个或一组进程发送消息通知它它们发生了某种事件如进程终止时要通知父进程 进程控制有些进程希望完全控制另一个进程的执行如Debug进程此时控制进程希望能够拦截另一个进程的所有陷入和异常并能够及时知道它的状态改变 总得来说实现进程间通信就是为了进程之间能够协同完成某项任务 如何实现进程间通信 进程间通信起初有很多不同的的相关协议随着不断的实践发展目前主要有两个主流的通信规则一个是System V另一个是POSIX POSIX让通信过程可以跨主机 System V聚焦在本地通信 由于System V由于制定的比较早不支持跨主机间的通信在今天属于比较陈旧的标准了因此我们会将更多精力放在POSIX上而System V我们关注比较重要的共享内存的概念 管道通信 管道通信主要是借助文件系统来实现的怎么理解呢我们假设现在系统上的进程A和进程B要互相通信A不能直接去B里面读数据因为进程具有独立性那该怎么办呢这就需要找一块空间C空间C用来存放通信双方通信的数据现在进程A要给B发送数据那么A和B要向系统声明建立连接申请一块空间C然后A往空间C里发送数据B往空间C里读取数据这样A就实现了和B的通信这块空间C就像一根管道一样连接着A与B整个管道通信的基本原理就是如此当然这只解释了管道名称的由来并没有解释管道通信是借助文件系统来实现的 我们要理清楚如何让两个进程读取到同一块内存空间如果看过IO篇的同学应该会想到那就是通过文件进程从磁盘中或除自身以外的其他可读写的内存区域中读取或写入数据都是通过文件系统来解决的只要系统在内存中创建一个文件A进程打开这个文件B进程也打开这个文件那么A与B就通过这个文件连接起来进行通信了这就是管道通信是借助文件系统来实现的原因 管道通信具体分为匿名管道通信和命名管道通信接下来跟随笔者逐个来了解什么是匿名通信和命名通信它们的作用是什么 匿名管道通信  经过上述的说明我们已经明白了管道通信就是用来实现进程与进程之间的通信但是进程与进程之间的通信也分为两种一种是父子进程或子兄弟进程之间的通信另一种则是没有亲属关系的进程间的通信 匿名管道通信就是用来解决有父子或兄弟关系的进程间通信在敲Linux代码时经常会用到匿名管道通信例如ps ajx | grep pid这个命令是用来查询进程id为pid的进程状态ps ajx是查询当前系统所有的进程状态而grep则是筛选函数用来筛选进程id为pid的进程两者之间就是通过管道进行数据通信也就是命令中的符号 |学完匿名管道通信你会彻底理解这个命令的实现原理接下来我们以父子进程间通信为例来讲解匿名管道通信 父子进程之间是共享代码和数据的但是随着程序的进行数据是会发生变化的而数据一旦发生变化就会触发写时拷贝父进程与子进程的数据就存放到了不同的地方这个时候双方又该如何进行数据交换呢这就是匿名管道通信要研究的东西 我们知道子进程会继承父进程的代码和数据那么父子进程要想进行通信那么父进程就要向操作系统声明通信也就是创建一个管道创建管道的代码如下 #include unistd.h 功能:创建一无名管道int pipe(int fd[2]);fd文件描述符数组,其中fd[0]表示读端, fd[1]表示写端 返回值:成功返回0失败返回错误代码注意该函数的参数是输出型参数在传参fd时要先创建fd也就是事先声明 int fd[2]; 这段代码中的内容笔者慢慢解释前面我们说过创建一个管道也就是系统在内存中创建一个文件进程A与进程B通过这个文件互相读取数据这就涉及到另一个问题如果进程A和进程B可以双向通信即都可向管道文件中读写数据那么到时候进程A与B又该如何分辨自己该读取哪部分数据呢 可能你会说等A写完B赶紧读然后B再写A再读这样会有潜在的隐患因为A写的时候你要阻止B写入如果这个时候B有很重要的数据写入就造成数据丢失而且要实现这种功能就可能要改变文件系统的相关结构 因此我们规定管道通信都是单向通信创建一个管道时只能由一方负责写一方负责读这是在创建管道时就要决定好的如果要实现双方都可以读写那就创建两个管道创建两个管道无非是创建两个文件罢了开销并不大 管道的通信是单向的那么如何确定哪一方是读方哪一方是写方呢解决办法就是让父进程以读和写两种形式分别打开管道文件也就是我们需要一个数组这个数组只有两个元素用来记录以读的形式打开管道文件的fd以及以写的形式打开管道文件的fd 然后根据相关情况选择关闭其中一个这也是为什么在声明管道通信前要先声明 int fd[2];这个语句的原因这个语句就是用来记录进程分别以读写端打开管道文件的fd int main() {int fd[2];int check pipe(fd);if (check ! 0) {printf(create pipe error\n);return 0;}} 父进程在创建子进程时子进程会拷贝一份父进程的进程地址空间同样的子进程也会拷贝父进程的文件描述符表 int main() {int fd[2];int check pipe(fd);if (check ! 0) {printf(create pipe error\n);return 0;}pid_t id fork();if (id 0) { /*执行父进程代码*/ };if (id 0) { /*执行子进程代码*/ };return 0;} 接下来我们明确父子进程谁是读端谁是写端就可以进行通信了这里我们让父进程写数据给子进程那么父进程就要关闭自己的读端子进程就要关闭自己的写段 fd[0]是读端fd[1]是写段 巧记按照读音的顺序读写01正好对应。还有1像一支笔所以是写端0像张开的嘴所以是读端 int main() {int fd[2];int check pipe(fd);if (check ! 0) {printf(create pipe error\n);return 0;}pid_t id fork();if (id 0) { close(fd[0]);/*关闭父进程的读端接着执行父进程代码*/ };if (id 0) { close(fd[1]);/*关闭子进程的写端接着执行子进程代码*/ };return 0;} 现在读写双方都确定了那写方如何给读方发数据读方又如何读取写方的数据呢 想想我们进程如何向进程中写入或读数据呢没错就是使用read和write函数接下来通过一个demo来看看这个通信过程 #includestdio.h #includestring.h #includeunistd.h #includestdlib.h #includesys/stat.h #includesys/types.h #includefcntl.h #includesys/wait.hint main() {int fd[2];int check pipe(fd);char test_buff[64] this is a communication test;if (check ! 0) { printf(create pipe error); return 0; }pid_t id fork();if (id 0) {close(fd[0]);write(fd[1], test_buff, sizeof(test_buff));wait();}if (id 0) {close(fd[1]);memset(test_buff, 0, sizeof(test_buff));read(fd[0], test_buff, sizeof(test_buff));printf(测试结果%s\n, test_buff);}return 0; } 我们成功实现了父子进程之间的通信接下来我们修改部分代码然后刨析一下通信的过程 如下是修改后的代码以及运行结果 #includeiostream #include string.h #include unistd.h #include stdlib.h #include sys/stat.h #include sys/types.h #include fcntl.h #includesys/wait.husing namespace std;int main() {int fd[2];int check pipe(fd);char test_buff[64] this is a communication test;if (check ! 0){std::cout create pipe error endl;return 0;}pid_t id fork();if (id 0){close(fd[0]);write(fd[1], test_buff, sizeof(test_buff));std::cout 我是父进程我的pid是getpid() endl;}if (id 0){close(fd[1]);while (true){sleep(1);memset(test_buff, 0, sizeof(test_buff));read(fd[0], test_buff, sizeof(test_buff)-1);std::cout 我是子进程我的pid是getpid() endl;std::cout test_buff endl;}}wait(nullptr);return 0; } 观察运行结果可以发现子进程循环两次后就卡在了那里不动了这是什么原因呢 这是因为read函数是一个阻塞式函数在上述程序中父进程往管道中写入一次数据后就进入了wait阻塞等待回收子进程子进程则是循环从管道中读取数据等到把管道中的数据读完的时候而父进程又没有关闭它的写端此时子进程的read函数就会进入读堵塞状态等待父进程继续向管道中写入数据父进程已经进入了进程阻塞等待自然不会再向管道中写入数据因此就进入了卡死状态 细心的小伙伴可能会有疑惑如果父进程只向管道中写入一次数据的话那么子进程读取一次就应该将数据读取完了呀子进程循环一次就该进入堵塞而运行结果显示子进程的循环进行了两次呢这是因为我们使用write函数进行写入时写入的大小是sizeof(test_buff)也就是64个字节而我们用read函数读取数据的时候读取的是sizeof(test_buff)-1也就是63个字节此时管道中还剩一个字节管道并不为空因此read函数还可以读取一次所以循环就进行了两次 可能你会想为什么要读取sizeof(test_buff)-1个字节呢一次读完不好吗这是因为在C语言中有些函数会自动给字符数组的末尾添加/0而有的函数又不会自动添加如果一次读完遇到了末尾自动添加/0的函数就会将末尾的数据给覆盖掉导致数据丢失因此在不能分辨某个函数是否会自动在字符末尾添加/0的时候为了安全我们统一把字符数组的最后一位给留出来也就是数据只读取字符数组大小-1个 上述的情况是父进程进入阻塞等待时并没有关闭写端导致子进程的read函数误认为父进程还会向管道中写入数据于是就进入阻塞状态一直等待。 如果父进程写完了并且关闭了自己的写端呢如果管道中还有数据那么子进程的read函数会继续读取数据如果管道中没有数据了那么read函数就会返回0不会进入阻塞等待状态因此在循环读取的场景下一定要注意接收read函数的返回值不然会进入死循环的状态的 如果父进程往管道中写入的数据很快而子进程读取的速度比较慢的话会出现什么情况呢我们前面说过管道通信文件是借助文件系统实现的但是管道通信文件跟一般的文件还不太一样管道通信文件不像普通文件一样可以存放到磁盘中管道通信文件不存放到磁盘上和磁盘没有关系且没有inode是操作系统临时分配的一块固定大小的内存我们也称其为管道缓冲区所以当写的速度太快读的速度太慢管道缓冲区被写满的时候此时写方就会进入写入阻塞状态直到缓冲区足够再次容纳写入的数据时才会再次允许写入 还有一种场景如果写方还在继续向管道缓冲区写入数据时而读方却关闭了读端那么此时系统就会终止并杀死写端因为读方都已经关闭读端了再写也没有意义了 说了这么多貌似并没有解释为什么会叫匿名管道这是因为父子进程之间进行通信时临时创建的这个管道文件并没有对应的文件名和inode只是系统分配的一块内存空间可以以文件的形式被父子进程打开或关闭这一切工作都在不知不觉中由OS全部完成了所以称为匿名管道等命名管道文件看完也可以回头对比着理解 现在我们回过头来理解开头讲的命令ps ajx | grep pid 管道符|用于将一个命令的输出作为另一个命令的输入。在这个命令中ps ajx命令的输出将作为grep pid命令的输入。 当这个命令在shell中执行时shell会创建一个匿名管道。ps ajx命令作为管道的写端将其输出写入管道而grep pid命令作为管道的读端从管道中读取输入。 因此ps ajx和grep pid都作为shell的子进程通过匿名管道进行通信。ps ajx将其输出写入管道而grep pid从管道中读取数据实现了两个命令之间的通信 命名管道通信 匿名管道应用的一个限制就是只能在具有共同祖先具有亲缘关系的进程间通信 如果我们想在不相关的进程之间交换数据可以使用FIFO文件来做这项工作它经常被称为命名管道命名管道是一种特殊类型的文件 命名管道可以从命令行上创建命令行方法是使用下面这个命令 $ mkfifo filename 命名管道也可以从程序里创建相关函数有 int mkfifo(const char *filename,mode_t mode); 除了创建一个命名管道在不使用的时候需要由创建方取消命名管道连接 int unlink(const char *pathname); int main() {umask(0);if ( mkfifo(name_pipe_file, 0644) -1) perror(create name_pipe fail), exit(0);return 0; }//在程序中创建命令管道第二个参数是设置该命名管道文件的权限 运行结束会出现这么个文件 命名管道与匿名管道之间的区别 匿名管道由pipe函数创建并打开。 命名管道由mkfifo函数创建打开用open FIFO命名管道与pipe匿名管道之间唯一的区别在它们创建与打开的方式不同一但这些工作完成之后它们具有相同的语义 匿名管道的打开规则 如果当前打开操作是为读而打开FIFO时O_NONBLOCK disable阻塞直到有相应进程为写而打开该FIFO O_NONBLOCK enable立刻返回成功 如果当前打开操作是为写而打开FIFO时 O_NONBLOCK disable阻塞直到有相应进程为读而打开该FIFO O_NONBLOCK enable立刻返回失败错误码为ENXIO  父子间通信子可以继承父的文件描述符表父子生来就指向相同的文件故而可以使用匿名通信的形式 两个不相干的进程要想指向同一个文件进行通信只能我们人为创建一个命名管道文件让两个进程都指向这个命名管道文件与磁盘进行IO操作的速度相较于内存来说非常慢没必要为了扩大管道缓冲区的容量将管道缓冲区的数据写往磁盘再读出来这会严重影响通信速度故而管道通信都不会与磁盘进行IO 下面是测试命名管道通信的demo大家可以自行测试一下 /* process A */#includestdio.h #includeunistd.h #includestdlib.h #includesys/stat.h #includesys/types.h #includefcntl.hint main() { umask(0);if ( mkfifo(name_pipe_file, 0644) -1) perror(create name_pipe fail), exit(0);int fd open(name_pipe_file, O_RDWR | O_APPEND);if (fd 0) perror(open name_pipe_file fail), exit(0);//send message to process Bwhile(true){char buff[1024] hey ,thiss process A, can you receive me?;int n write(fd, buff, sizeof(buff));if(n 0) perror(write fail), exit(0);sleep(1);}return 0; }// process B #includestdio.h #includeunistd.h #includestdlib.h #includesys/stat.h #includesys/types.h #includefcntl.hint main() {int fd open(name_pipe_file, O_RDWR | O_APPEND);if (fd 0) perror(open name_pipe_file fail), exit(0);//receive message from name_pipewhile(true){char buff[1024];int n read(fd, buff, sizeof(buff));if (n 0) perror(read fail), exit(0);fprintf(stdout, %s\n, buff);sprintf(buff, %s, YES, thiss process B, I can receive your message);fprintf(stdout, %s\n, buff);printf(\n);}return 0; } 共享内存  前面说过管道通信只是进程间通信的其中一种方式接下来我们共同探讨另一种进程间通信形式——共享内存不管用哪种通信方法通信的本质就是让通信双方能够使用看到和使用同一块空间有了前面内容的铺垫我们理解共享内存的理论并不困难但共享内存的操作稍微有一些复杂不过请放心笔者会按照步骤顺序逐步进行只要按照正常步骤走就能减少缺漏的情况 如上图这是两个普通进程A和B在系统上工作的原理图现在想让进程A和B之间进行通信共享内存的方法是如何做的呢首先由通信的其中一方负责向系统申请共享内存通信这里就让进程A负责好了OS收到请求后在物理内存划出一块内存区域用来这保证了进程A和进程B能够看到并使用同一块内存空间如下图的红色操作 共享内存申请好了但是并不意味着就可以直接用了因为进程AB的页表里并没有关于共享内存区域的映射因此进程A和B要分别与共享内存区域进行挂接挂接的过程就是将共享内存区域的物理地址添加到进程的页表映射中这样进程就能通过页表映射到共享内存区域了如下图的蓝色操作 等到挂接完成后进程A和B就能看到并使用同一块内存空间了至此就可以开始通信等到通信结束之后通信双方要分别取消掉对共享内存区域的挂接操作如下图绿色操作 取消挂接了并不算彻底结束了因为共享内存的申请是直接在物理内存上进行的不会随着进程的退出而释放只有手动释放或者系统重启的时候才会释放因此进程不再通信后应当由共享内存申请方在进程退出前释放共享内存如下图黄色操作  至此共享内存的原理已经完成总共分成了4个步骤实现共享内存通信接下来就是实践检验理论的部分了 首先就是进程A向系统申请共享内存通信那么该用哪些系统调用来完成呢 int shmget(key_t key, size_t size, int shmflg)  功能用来创建共享内存 key_t key共享内存的字段标识 size_t size要申请的共享内存的大小 shmflg由九个权限标志构成它们的用法和创建文件时使用的mode模式标志是一样的 常用的标志有两个 1.IPC_CREAT如果该共享内存字段已经存在就获取它如果不存在就创建它 2.IPC_EXCL搭配IPC_CREATE使用如果创建失败就返回错误码 返回值成功返回一个非负整数即该共享内存段的标识码失败返回-1 这里需要解释一下key共享内存是用来进程间通信的那么系统中那么多进程肯定会存在很多的共享内存那么系统要管理这些共享内存就要给这些共享内存标号标明它的唯一性这个key值就是这段共享内存在系统中的唯一性编号通过这个唯一性编号以及你要申请的共享内存的大小系统就可以帮你申请一块共享内存了 key的值通过ftok()函数来创建ftok()的说明如下 简单来说就是给一个文件路径名和一个int值那么ftok函数就会生成一个能唯一标识共享内存的key值也就是shmget()函数中第一个参数的key值 当shmget()三个参数齐全创键共享内存成功的时候就会返回一个共享内存的标识码shmid 可能你会惊讶刚才用ftok已经生成了标识共享内存的码怎么这里又返回了一个 其实这两个码都可以用来标识共享内存shmid与key的关系就类似于文件系统中的fd和inodekey就像inode一样是给系统看的shmid和fd类似是给应用层的进程使用的为何要多此一举呢这是为了系统层和应用层之间的解耦避免因应用层的shmid出现错误而影响了系统层的正常工作 接下来陈述共享内存创建的过程当进程A和B开始通信时进程A和B会根据指定的路径和int值用ftok函数生成相同的key值进程A来负责申请共享内存填上key值申请共享内存的大小和相关标志位shmget()函数会返回一个shmid这个shmid是供进程来标识共享内存的 接下来进程B同样使用shmget()函数因为要互相通信进程A和B使用的是相同的路径和int值所以ftok生成的key值就相同将key值共享内存大小相关标志位填完以后shmget函数会检测出当前这个key值已经申请过共享内存于是将这个key值标识的共享内存的shmid返回去至此进程B和进程A都拿到了相同的shmid表明进程AB都能够找到这块共享内存这便是第一步的整个过程 进程A和B都能够通过shmid找到用于通信的共享内存段但是不意味着可以直接开始通信接下来双方要执行前面说过的第二个步骤就是与共享内存段建立连接 void *shmat(int shmid, const void *shmaddr, int shmflg); shmaddr表示从哪个地址处开始连接我们填null会默认从共享内存段的首地址处开始连接shmflg是根据实际需要填写的标志位我们用不到填0就好 将三个参数填入后shmat就可以连接了连接成功会返回一个地址通过这个地址就可以使用共享内存了连接失败会返回-1 有了地址使用共享内存就和使用指针以及数组一样就可以进行从中写入数据读取数据等操作笔者将在后面用实例展示 接下来是通信结束取消挂接的操作 int shmdt(const void *shmaddr); 直接往参数中填入挂接时返回的地址就可以取消挂接了 最后由共享内存申请方释放掉申请的共享内存不然进程退出后共享内存并不会自动释放 int shmctl(int shmid, int cmd, struct shmid_ds *buf); 第二个参数填入IPC_REID表示移除共享内存第三个参数不需要操心直接填null 至此就可以移除共享内存通信结束 用一个demo来演示共享内存的用法 //通信双方所引用的头文件 share_test.h#includeiostream #includeunistd.h #includestdio.h #includesys/types.h #includesys/ipc.h #includesys/shm.h #includesys/stat.h #includefcntl.h #includecstring//如下两个定义用于ftok创建唯一的标识符 #define PATHNAME . #define PROJ_ID 0x22 //通信进程A读取共享内存的信息同时负责共享内存的申请和释放 #includeshare_test.hint main() {key_t _key ftok(PATHNAME, PROJ_ID);if (_key 0) perror(get key fail), exit(0);//0666是权限标志即申请的共享内存有哪些可用权限不加权限无法读写int shmid shmget(_key, 4096, IPC_CREAT|IPC_EXCL|0666);if (shmid 0) perror(shmget fail), exit(0);char *start (char*)shmat(shmid, NULL, 0);for (int i 0; i 45; i){printf(%s\n, start);sleep(1);}sleep(3);shmdt(start);int n shmctl(shmid, IPC_RMID, NULL);if (n 0) perror(destory share_memory fail);return 0; } //通信进程B往共享内存中写入数据 #includeshare_test.hint main() {key_t _key ftok(PATHNAME, PROJ_ID);if (_key 0) perror(get key fail), exit(0);int shmid shmget(_key, 4096, IPC_CREAT);if (shmid 0) perror(shmget fail), exit(0);char *start (char*)shmat(shmid, NULL, 0);for (int i 0; i 26; i ){start[i] Ai;sleep(1);}shmdt(start);sleep(2);return 0; } 共享内存的优缺点 共享内存的优点所有的进程间通信速度是最快的 能很大程度较少数据的拷贝次数 共享内存的缺点不支持同步和互斥操作没有对数据做任何保护 不支持同步与互斥也就是说允许同时写入或读取数据这会导致数据杂乱无法使用大家可以使用此篇文章管道的知识来帮助共享内存实现互斥功能 消息队列  消息队列也是进程间通信的一种方式不过消息队列现在的应用场景很少几乎不怎么用因此这里笔者大概描述一下消息队列的工作原理不再深入细究 消息队列这种通信形式可以看作是OS为通信双方建立一个消息队列结构双方的数据交换就通过消息队列进行在这个消息队列的数据元素中包含该进程的标识符以及该进程要写入数据读取方则可以根据数据元素的进程标识符来确定是否要接收该进程的数据 这个通信原理很类似管道不过和管道不同的是管道发送的是数据流要人为判断数据边界消息队列的数据类型是一个独立的结构每发一次数据都被独立包装消息队列的数据会长期保存但当容量填满时就会拒绝接收消息直到空间足够并且消息队列允许通信双方同时读写 信号量 在了解信号量是什么之前我们先来了解一些概念 公共资源被多个进程同时可以访问的资源 两个或多个进程之间相互通信所能看到的共同的内容就是公共资源公共资源的概念不难理解因为是公共资源所以多个进程就可以同时修改或读取其他进程没有阻拦的权利这会导致数据不一致前一个进程刚准备读后一个进程立马把数据更改了这些问题要归究到公共资源受不受保护 我们称被保护起来的公共资源为临界资源不被保护的就是非临界资源 同样的道理进程中肯定有对应的代码来访问这些临界资源访问这些临界资源的代码我们就称之为临界区其他的代码称为非临界区 那么如何做到公共资源受到保护呢那就是支持同步与互斥功能在线程这部分内容会详细说明要支持同步与互斥功能就要保证操作的原子性 所谓原子性即不可分割性一个操作要么成功完成要么执行失败没有中间状态 信号量究竟是什么呢信号量我们可以理解成是一个计数器用来统计公共资源的数目这就像看演出一样演出的门票数量是一定的门票这种可以被公众购买的就是公共资源那么门票的数量就是信号量如果门票数量没了那么这场演出就没法看了 进程申请公共资源也是如此首先公共资源是有限的信号量就是用来记录公共资源数目的进程要想访问公共资源首先要先申请信号量这就要求信号量本身就得能被所有的进程看到而能被所有进程看到和使用的资源不就是公共资源嘛因此信号量本身就是公共资源其次进程每申请一份资源信号量的数目就会--进程每释放一份资源信号量的数目就会这就要保证--操作必须是原子性的要么完成要么失败 至此我们就一同完成了进程间通信的学习这篇文章中比较重要的部分就是管道通信和共享内存了这两种也是笔者着重描述的通信形式像消息队列这种使用情况不多的通信形式感兴趣可以自行查阅信号量我们在后面还会谈到
http://www.pierceye.com/news/418167/

相关文章:

  • 免费建站哪家好网站商城建设合同免费下载
  • 网站开发filter北京互联网
  • 德州市市政工程建设总公司网站设计公司的运营模式
  • 网站源码怎么弄境外注册网站
  • 肥城网站建设视频解析接口网站怎么做
  • 深圳做互联网教网站公司五百亿网站建设
  • 如何建自己网站周口网站建设费用
  • 延安网站建设哪家专业网站建设的大功效
  • 做网站交互demo工具服务器中安装wordpress
  • 2017年网站建设市场分析2345浏览器官网网址
  • 超大型网站建设怎么打广告吸引客户
  • 阳泉 网站建设合作国际网站设计
  • 东莞网站优化快速排名wordpress自适应设置宽度
  • wordpress的站点地址怎么设置青岛seo网站建设
  • wordpress 获取文章标签泰安企业网站seo
  • 网站可分为哪两种类型jsp网站建设项目实战 pdf
  • 科技类网站简介怎么做网站建设公司的工资
  • 东莞网站推广怎么做网站备案和备案的区别
  • 免费的舆情网站app开放平台设计方案
  • 昆明驿站网站建设程序做网站好还是app好
  • 提供网站推广公司电话室内设计好不好学
  • 小型网站网站建设需要做网页的素材网站
  • 圣诞节网站模板大兴企业官网网站建设
  • 法国化妆品进口报关做网站贵州两学一做网站
  • 青海环保网站建设公司wordpress版权怎
  • 砀山网站建设大凤号 网站建设
  • 汕头站什么是网站优化主要包括那几个
  • 买了一个域名如何做网站做歌手的网站
  • 制作精美网站建设服务周到外贸没有公司 如何做企业网站
  • jsp手机销售网站的建设做网站的收钱不管了