管道的三种使用方案中,唯一正确而安全的使用方法

系统自带的管道方法:
全局变量:
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]]; 见我的文章管道,信号量,共享内存,socket的实际使用场景和NSPipe管道的使用 (http://blog.csdn.net/jia12216/article/details/47360637
它的缺点也很显然,线程被杀,管道资源被回收时,你访问该管道,会出现管道破裂的系统级崩溃。详细见我的文章。
Signal 13 was raised(SIGPIPE管道破裂)
http://blog.csdn.net/jia12216/article/details/50844013

所以还时用系统级别的管道最安全,可以通过写管道是否可以写来判断管道是否可用。
这样使用申请管道也是错误的,因为你的线程申请的管道,在外部要可以用,肯定要能用,你申请个局部变量,等你离开线程时,你再使用管道,你就访问了空指针,造成管道破裂崩溃。下面是例子
int pipeSNO[2];
pipeSNO[0] = -1;
pipeSNO[1] = -1;
pipe(pipeSNO);
self.fdGuardModifyWaitTimeReadPipe = pipeSNO[0];
self.fdGuardModifyWaitTimeWritePipe = pipeSNO[1];
int set = 1;
setsockopt(self.fdGuardModifyWaitTimeReadPipe, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
int write = 1;
setsockopt(self.fdGuardModifyWaitTimeWritePipe, SOL_SOCKET, SO_NOSIGPIPE, (void *)&write, sizeof(int));
看来你向获得强大的功能,那么你就要从操作系统层做起,并且自己负责管道的申请和释放,不受系统ARC自动管理内存控制。下面是正确而强大的使用管道的部分例子,
申请管道部分:
if(self.fdGuardPipeHead != nil)
{
close(self.fdGuardModifyWaitTimeReadPipe);
close(self.fdGuardModifyWaitTimeWritePipe);
free(self.fdGuardPipeHead);
}
self.fdGuardPipeHead = malloc(2 * sizeof(int));
_fdGuardPipeHead[0] = -1;
_fdGuardPipeHead[1] = -1;
pipe(_fdGuardPipeHead);
self.fdGuardModifyWaitTimeReadPipe = _fdGuardPipeHead[0];
self.fdGuardModifyWaitTimeWritePipe = _fdGuardPipeHead[1];
int set = 1;
setsockopt(self.fdGuardModifyWaitTimeReadPipe, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
int write = 1;
setsockopt(self.fdGuardModifyWaitTimeWritePipe, SOL_SOCKET, SO_NOSIGPIPE, (void *)&write, sizeof(int));
[self creatSocketConnection];

发送于异常判断
//通过长连接的监控管道发送char *格式的消息
-(BOOL)sendMessageBySocketMonitorPipeWithCharArr : (const char *)message
{
NSUInteger len = 0;
len = strlen(message);
if(0 == len)
{
return YES;
}
unsigned char input_msg[BUFFER_SIZE] = {0};
memcpy(input_msg, message, len);;
@try {
long ret = write(self.fdWritePipe, input_msg, len);
if(ret != len)
{
[self processSocketPipeClosed];
return NO;
}
else
{
return YES;
}
}
@catch (NSException *exception) {
FLDDLogInfo(@”exception:%@”, exception);
[self processSocketPipeClosed];
return NO;
}
@finally {

}

}

关闭管道的操作
-(void)processSocketPipeClosed
{
FLDDLogDebug(@”函数”);
if(self.socketThreadPipeHead != nil)
{
close(self.fdReadPipe);
close(self.fdWritePipe);
free(self.socketThreadPipeHead);
}

self.socketThreadPipeHead = malloc(2 * sizeof(int));
_socketThreadPipeHead[0] = -1;
_socketThreadPipeHead[1] = -1;
pipe(_socketThreadPipeHead);
self.fdReadPipe = _socketThreadPipeHead[0];
self.fdWritePipe = _socketThreadPipeHead[1];
int setPipe = 1;
setsockopt(self.fdReadPipe, SOL_SOCKET, SO_NOSIGPIPE, (void *)&setPipe, sizeof(int));
int writePipe = 1;
setsockopt(self.fdWritePipe, SOL_SOCKET, SO_NOSIGPIPE, (void *)&writePipe, sizeof(int));
if(![self sendMessageByPipeWithCharArr : g_guardThreadCheckIfNormal])
{
    //守护线程的监控管道被系统关闭,需要建立守护线程时立刻重新建立长连接,防止无法通过监控管道控制守护线程
    _connectTime = (long long)[[NSDate date] timeIntervalSince1970] - SOCKET_CONNECT_ABORT_WAIT_TIME - 1;
    _currentSocketThreadDic = nil;
    _socketThreadDic = nil;
    if(self.fd > 0)
    {
        close(self.fd);
    }
    self.socketConnectStat = SOCKECT_CONNECT_ABNORMAL;
}
else
{
    [self creatSocketConnection];
}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值