管道通常用在两个线程间通信或进程间通信

转载 2016年06月01日 16:42:08
管道,信号量,共享内存,socket的实际使用场景和NSPipe管道的使用

找了很久也没有找到NSPipe在IOS方面的常规使用()。我试了半天终于找到它的正常的使用方法,我想对很多想使用管道会有很大的帮助。阿门,看来我是第一个吃螃蟹的人。 
由于线程又称轻量级别的进程,属于广义进程范围。最显著的特征是线程间可以通过所属的线程共享资源和全局变量;进程间不能共享全局变量。 
进程和线程间四大通信机制:管道,信号量,共享内存,socket。 
四大通信机制的实际使用场景 
管道是单向的、先进先出的,它把一个进程的输出和另一个进程的输入连接在一起。一个进程(写进程)在管道的尾部写入数据,另一个进程(读进程)从管道的头部读出数据。NSPipe包含两个文件描述符,读文件描述符合写文件描述。管道通常用在两个线程间通信或进程间通信。由于不能进程间不能共享全局变量,那么两个进程间要得到文件描述符FD,那么你只有通过读写本地文件来获得管道读文件描述符和写文件描述符。由于不同电脑的文件描述符不互相统属,所以管道不能对不同手机(电脑)间通信。不同电脑间通信用socket。若在应用中管道文件描述符全局变量,读端和写端都能访问到,那么他们肯定在一进程内,两个进程间肯定不可能访问到共同的全局变量。由于读写文件需要时间和一个写一个读的情况,所以不同进程间通信最好别用管道,除非你的管道需要长期保留并且保持可用,不常换管道描述才能用写FD到文件的方式。最佳的方式是用信号量。但是信号量只能当开关判断没有办法传递数据块,信号量本手机(电脑)唯一,所以可以实现进程间互相控制。更高级的你可以用SOCKET通信。注意在安卓环境下不能使用C语言调用共享内存,用JAVA可以调用共享内存,这个功能被安卓系统阉割了。IOS对共享内存的支持没有试过,我只玩过用C++(MFC)写过windows下的线程间共享内存。 
所以按照侠义进程和线程概念,不考虑分布式系统时他们4种最适合的通信场景是: 
管道可以直接实现线程间通信,进程间通信的功能受到限制,本机有效。原因是申请管道是,读写FD的值不可以提前预知,进程间不能共享全局变量,所以只能用通过HTTTP请求或写文件的方式告知另一个进程你申请的管道读写文件描述符号。 
共享内存,可以直接实现线程间通信,进程间通信的功能受到限制,本机有效。原因是共享内存的地址不可以提前预知,由于进程间不能共享全局变量,所以只能用通过HTTTP请求或写文件的方式告知另一个进程你申请的共享内存的地址。 
信号量,可以实现进程间通信,可以实现线程间通信,本机有效,不能传递数据块。它是通过申请一个约定字符串来找到一个信号量的,所以它可以跨进程。 
SOCKET,超级强大,可以是实现进程间通信,线程间通信,不同系统间通信,不同主机间通信,跨越各种复杂网络在不同设备间通信,你可以把他理解为一个超级文件,两端打开端口,中间形成一个通道,你可以通过两端的读写描述符(FD),向里面写数据和读数据。

一台电脑的文件描述符最多理论上有65535,也就是能连接65535连接个socket,实际除掉保留的文件描述符,socket分配冲突问题,实际上只能保证连接20000个socket长连接,若再多的socket,只能采用负载均衡的策略,服务器需要搞集群了。 
通过NSPipe创建一个管道,pipe有读端和写端。 
然后通过写文件描述符(FD)写数据就可以,通过select函数判断是否可读,若可读就通过读文件描述符读到读缓冲区里就可以了。我已经实际实现。其它方式都被阻塞,纯属扯蛋,误人子弟。以前我在华为做协议层时,用的是linux系统的管道处理(int pipe_fd[2];pid_t pid;),然后编程so包,能在安卓和苹果手机上运行。那样实现太麻烦,不适合我们小门小户的IOS原生态开发。先不说pid_t 在OC里是否直接支持,光那个int pipe_fd[2];就让你无解。OC不支持全局变量是这种数组类型,不是他的基本类型,放在函数内部当局部变量用,函数一旦运行结束它就被释放了,上那里找它去。所以还是找OC自己的NSPipe去吧!NSPipe那个读管道函数就是个坑爹的大毛坑,一旦调用就卡死那里,如你调用NSData *stdOutData = [reader availableData];这个读管道数据函数绝对会程序卡在哪里,害得我申请管道和向管道内写数据用他的NSPipe,读管道用文件描述符,这也是没有见到别人用NSPipe的一个重要原因吧! 
下面是事例: 
全局变量: 
NSPipe * pipe = [NSPipe pipe] ; 
NSFileHandle *pipeReadHandle = [pipe fileHandleForReading] ; 
int pipeReadFd = [[pipe fileHandleForReading] fileDescriptor], fd]; 
int pipeWriteFd = [[pipe fileHandleForWriting] fileDescriptor], fd];

写管道处: 
[self.pipeWriteFd writeData: [@”send” dataUsingEncoding: NSASCIIStringEncoding]];

读管道处: 
FD_ZERO(&read_fd_set); 
FD_SET(self.pipeReadFd , &read_fd_set); 
tv.tv_sec = 1; 
tv.tv_usec = 0; 
//socket一般都处于可写状态,除了网卡满了写不进去的罕见情况,所以该处侦听一般都是立刻响应

                          ret = select(self.pipeReadFd+ 1, &read_fd_set , NULL, NULL, &tv);


                            if (FD_ISSET(self.fdReadPipe, &read_fd_set))
                            {
                                FLDDLogDebug(@"ret2= %ld\n", ret);

                                long nbytes;
                                unsigned char readBuffer[48] = {0};
                                nbytes = read(self.fdReadPipe, readBuffer, 20);
                                if (nbytes <= 0) {
                                    FLDDLogDebug(@"no data.");
                                }
                                else
                                {
                                    readBuffer[47] = '\n';
                                    str = [[NSString alloc] initWithString:[NSString stringWithFormat:@"%s", readBuffer]];
                                    FLDDLogDebug(@"data:%@", str);
                                    if([str hasPrefix:@",cancel quit"])
                                    {
                                        self.isCloseSocket = NO;
                                        FLDDLogDebug(@"收到取消关闭socket管道消息:%@", str);
                                        //                                        break;
                                    }
                                    else if([str hasPrefix:@"quit"])
                                    {
                                        self.isCloseSocket = YES;
                                        self.socketConnectStat = SOCKECT_CONNECT_INIT;
                                        FLDDLogDebug(@"收到关闭socket管道消息:%@,需要立刻结束socket线程", str);
                                        self.isCloseSocket = YES;
                                        //跳出循环,结束长连接线程,由于服务要求客户端不能主动关闭socket,需要服务器自己关闭socket,所以这里不需要关闭socket
                                        break;
                                    }
                                    else if([str hasPrefix:@"send"])
                                    {
                                        FLDDLogDebug(@"收到发送消息管道消息:%@", str);
                                        //                                        break;
                                    }
                                }

                            }

相关文章推荐

管道流实现两个线程间通信

Java中实现多线程间的通信主要通过两种方式:共享变量和管道流。共享变量一般通过加锁的方式来保证线程的安全性,在之前的多篇博客中已提供了多个例子,这里不赘述。知道在使用锁的过程中,注意锁作用的对象以及...

【Java】线程管道通讯

很多操作系统对于管道的吹嘘往往是天花龙凤, 好心点的就贴段伪代码给你看,为出书而出书的,就直接一堆概念堆在上面,让人根本看不懂, 如此简单的概念,明明几句话就解释清楚,有的书还专门开出一章来讨论这个问...

使用管道流和多线程完成以下任务要求: 一个线程对象t1 会从控制台中不停的读取信息,读到之后把数据交给管道输出流,把数据写到管道里面 ,另一个线程对象t2 不停的使用管道输入流从管道

使用管道流和多线程完成以下任务要求: 一个线程对象t1 会从控制台中不停的读取信息,读到之后把数据交给管道输出流,把数据写到管道里面 ,另一个线程对象t2 不停的使用管道输入流从管道...

MFC 多线程间通信

 AfxBeginThead全局变量参数传递消息传递线程通信 目录(?)[-] 线程间的通信 线程之间的通信简介全局变量方式参数传递方式消息传递方式线程同步法 ...

linux 线程或进程之间通过管道通信(pipe)

线程间通信: #include // printf #include // exit #include // pipe #include // strlen #include // pt...

多进程间通信之有名管道

有名管道  FIFO 一个进程以读方式打开,另一个以写方式打开才能正常运行只打开一端将阻塞。...
  • Al_xin
  • Al_xin
  • 2014年09月02日 17:17
  • 1050

【Linux】进程间通信之管道

每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数...
  • Scenlyf
  • Scenlyf
  • 2016年07月25日 21:05
  • 895

Linux的进程/线程间通信方式总结

Linux系统中的进程通信方式主要以下几种: 同一主机上的进程通信方式    * UNIX进程间通信方式: 包括管道(PIPE), 有名管道(FIFO), 和信号(Signal)    * Sy...

linux的Listen调用详解

listen系统可以使一台主机上的一个tcp socket在某个端口号被动侦听,等待来自其它主机的tcp socket的连接请求,下面是listen系统调用的函数原型: #inclu...

const用法总结以及构造函数、析构函数、拷贝构造函数的深入剖析

1. 用const时候,通常需要初始化: #include using namespace std; int main() { int const i; // error C2734: '...
  • stpeace
  • stpeace
  • 2013年05月14日 13:36
  • 700
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:管道通常用在两个线程间通信或进程间通信
举报原因:
原因补充:

(最多只允许输入30个字)