伪终端和多方向读写select编码

伪终端模型,主设备相当于键盘和显示器,而从设备相当于设备驱动。


打开主设备:

int open_ptym(char *slave_name, int buf_size){
	char *ptr;
	int fdm;
	#if 0 
	if((fdm = open("/dev/ptmx",O_RDWR))<0){
		perror("open ptmx\n");	
		return -1;
	}
	#endif
	if((fdm = posix_openpt(O_RDWR)) < 0){
		perror("open ptmx\n");	
		return -1;
	}
	/* 设置从设备的访问权限 */
	if(grantpt(fdm) < 0){
		perror("grantpt");
		close(fdm);
		return -2;
	}
	/* clear slave`s lock flag */
	if(unlockpt(fdm) < 0){
		perror("unlockpt");
		close(fdm);
		return -3;
	}

	if((ptr = (char *)ptsname(fdm)) == NULL){
		perror("ptsname");
		close(fdm);
		return -4;
	}
	strncpy(slave_name,ptr,buf_size);
	slave_name[buf_size - 1] = '\0';
	printf("fdm:%d slave_name:%s\n",fdm,slave_name);
	return fdm;
}


打开从设备:

int open_ptys(char *slave_name){
	int fds;
	if((fds = open(slave_name,O_RDWR)) < 0){
		perror("open slave");
		return -5;
	}
	printf("fds:%d\n",fds);
	return fds; }

登录后fork子程序为网络端服务,使用fds接受fdm方向过来的数据,而fdm的数据来自网络,针对fdm的进出和socket-fd的进出一共四个方向的i/o使用select处理:

int fork_bash(int *fdm_ret){
	int fds, fdm, ret;
	char slave_name[15];
	struct termios termios_my;
	struct winsize win_size;
	/* get termios/winsize */
	tcgetattr(STDIN_FILENO,&termios_my);
	ioctl(STDIN_FILENO,TIOCGWINSZ, (char *)&win_size);


	/* open primary pty */
	fdm = open_ptym(slave_name,15);
	if(fdm < 0){
		return -1;
	}

	int pid = fork();
	if(pid>0){
		*fdm_ret = fdm;
		return pid;		
	}else if(pid < 0){
		perror("fork fault!");
		return -1;
	}else if(pid == 0){
		/* create new session 控制终端丢失 */
		ret = setsid(); 
		if(ret < 0){
			return -1;
		}

		/* open slave pty 设置控制终端为此pty */
		fds = open_ptys(slave_name);
		if(fds < 0){
			return -1;
		}
		//*fds_ret = fds;
		/* set termios/winsize */
		tcsetattr(fds, TCSANOW, &termios_my);
		ioctl(fds, TIOCSWINSZ, (char *)&win_size);
		//ioctl(fds, TIOCSCTTY, (char *)0);

		/* stdin sdtout stderr bind pts*/
		if((ret = dup2(fds,STDIN_FILENO)) != STDIN_FILENO){
			return -1;
		}
		if((ret = dup2(fds,STDOUT_FILENO)) != STDOUT_FILENO){
			return -1;
		}
		if((ret = dup2(fds,STDERR_FILENO)) != STDERR_FILENO){
			return -1;
		}
		if(fds > 2){
			close(fds);
		}
		ret = execl("/bin/bash","bash",NULL);
		if(ret < 0){
			perror("execl err!");
			return -1;
		}
	}
}

select处理:

(这端代码未编译过,错了别找我,嘎嘎)

int loop_select(int fdm, int socket_fd){
	/* init fd_set */
	fd_set read_set,write_set, tmp_set;
	FD_ZERO(&read_set);
	FD_ZERO(&tmp_set);
	FD_ZERO(&write_set);
	FD_SET(fdm,&read_set);
	FD_SET(socket_fd,&read_set);
	tmp_set = read_set;

	/* init buffer */
	char buf_from_fdm[1024];
	char buf_from_socket[1024];
	memset(buf_from_socket, 0, 1024);
	memset(buf_from_fdm, 0, 1024);
	int buf_fdm_count= 0;
	int buf_socket_count = 0;

	/* select */
	struct timeval t;
	t.tv_sec = xx;	
	t.tv_usec = xxx;	
	int ret = 0;
	while(1){
		ret = select(Max(fdm,socket_fd)+1, &read_set, &write_set, NULL, &t);
		if(ret < 0){
			perror("select error:");
			return -1;
		}
		/* read fdm */
		if(FD_ISSET(fdm, &read_set)){
			ret = read(fdm, &buf_from_fdm[buf_fdm_count], 1024 - buf_fdm_count);
			if(ret < 0){
				if(errno != EINTR){
					perror("read fdm error:");
					return -1;
				}
			}else{
				buf_fdm_count += ret;
			}
		}
		/* read socket */
		if(FD_ISSET(socket, &read_set)){
			ret = read(socket, &buf_from_socket[buf_socket_count], 1024 - buf_socket_count);
			if(ret < 0){
				if(errno != EINTR){
					perror("read socket error:");
					return -1;
				}
			}else{
				buf_socket_count += ret;
			}
		}
		/* write socket */
		if(FD_ISSET(socket_fd, &write_set)){
			char *p = buf_from_socket;
			while(buf_socket_count != 0){
				ret = write(socket_fd, p, buf_socket_count);
				if(ret < 0){
					if(errno != EINTR){
						perror("write socket_fd error:");
						return -1;
					}else{
						continue;
					}
				}
				p += ret;
				buf_socket_count -= ret;
			}
		}
		/* write fdm */
		if(FD_ISSET(fdm, &write_set)){
			char *p = buf_from_socket;
			while(buf_fdm_count != 0){
				ret = write(fdm, p, buf_fdm_count);
				if(ret < 0){
					if(errno != EINTR){
						perror("write fdm error:");
						return -1;
					}else{
						continue;
					}
				}
				p += ret;
				buf_fdm_count -= ret;
			}
		}
		/* reset fd_set */
		read_set = tmpset;
		FD_ZERO(&write_set);
		if(buf_fdm_count > 0){
			FD_SET(socket_fd, &write_set);
		}
		if(buf_socket_count > 0){
			FD_SET(fdm, &write_set);
		}
	}	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值