目录

目录结构

ptsTalk.h

ptsTalk.c

示例程序

master.c

slave.c

makefile

效果:


pts为伪终端,他们之间的标准输出输入该如何进行交换呢?

目录结构

# tree
.
├── Makefile
├── master
├── master.c
├── ptsTalk
│?? ├── ptsTalk.c
│?? └── ptsTalk.h
├── slave
└── slave.c1 directory, 7 files

ptsTalk.h

#ifndef _TALK_PTS_H
#define _TALK_PTS_H 1#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/un.h>struct pts_id {
#define PTS_MAGIC   0xaab12cddint pts_magic;int pts_dev_name;int pts_pid;
};typedef enum {PTS_ON,PTS_OFF,
}pts_stat;typedef int (*pts_connect_fn)(struct pts_id*, pts_stat stat);int pts_master(pts_connect_fn fn);
int pts_slave(struct pts_id*);int pts_print(struct pts_id *pts, char *fmt, ...);#endif//_TALK_PTS_H

ptsTalk.c

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <pthread.h>
#include <sys/select.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <unistd.h>
#include <signal.h>
#include <termios.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/ioctl.h>#include "ptsTalk.h"#define __PTS_UNSOCKET_PATH     "/tmp/__pts_tell"#define PTS_MAX_SLAVE   10#define STR_LEN         256
#define PTS_PREFIX      "/dev/pts"pthread_t __pts_tell_tid;static int __pts_master_listenfd;static int __pts_tell_unsocket_server(const char *unix_path);
static int __pts_tell_unsocket_client(const char *unix_path);
static void* __pts_tell_master_task(void*arg);static int pts_get_id(struct pts_id *tellpts);void __pts_tell_unsocket_server_handle_sigint(int signum)
{printf("Catch the SIGINT signal.\n");close(__pts_master_listenfd);unlink(__PTS_UNSOCKET_PATH);exit(1);
}
void __pts_tell_unsocket_client_handle_sigint(int signum)
{printf("Catch the SIGINT signal.\n");exit(1);
}int pts_master(pts_connect_fn fn)
{return pthread_create(&__pts_tell_tid, NULL, &__pts_tell_master_task, fn);
}int pts_slave(struct pts_id *tpts)
{int connect_fd;int ret = 0;struct sockaddr_un srv_addr;int i;signal(SIGINT, __pts_tell_unsocket_client_handle_sigint);connect_fd = __pts_tell_unsocket_client(__PTS_UNSOCKET_PATH);struct pts_id tellpts;pts_get_id(&tellpts);write(connect_fd, &tellpts, sizeof(tellpts));   read(connect_fd, tpts, sizeof(struct pts_id)); close(connect_fd);
}static int pts_get_id(struct pts_id *tellpts)
{tellpts->pts_magic  = PTS_MAGIC;tellpts->pts_pid    = getpid();tellpts->pts_dev_name = 9999;char cmd[256] = {0};char str[256] = {0};sprintf(cmd, "ps -ef | grep %d | awk '{print $6}'", tellpts->pts_pid);FILE *fp = popen(cmd, "r");fgets(str, sizeof(str), fp);sscanf(str, "pts/%d", &tellpts->pts_dev_name);pclose(fp);return 0;
}static void* __pts_tell_master_task(void*arg)
{pts_connect_fn slave_connect_callback = (pts_connect_fn)arg;struct {int fd;struct pts_id ptsid;}slaves[PTS_MAX_SLAVE];int connfd; int ret = 0;int i;int len, msglen;struct sockaddr_un clt_addr, srv_addr;struct pts_id pts_tell;char msg[STR_LEN];int maxfd, maxi, nready; fd_set readset, allset, exceptset;int sockfd;signal(SIGINT, __pts_tell_unsocket_server_handle_sigint);__pts_master_listenfd = __pts_tell_unsocket_server(__PTS_UNSOCKET_PATH);setsockopt(__pts_master_listenfd,SOL_SOCKET,SO_REUSEADDR,NULL,0);setsockopt(__pts_master_listenfd,SOL_SOCKET,SO_REUSEPORT,NULL,0);for(i=0; i<PTS_MAX_SLAVE; ++i){slaves[i].fd = -1;}maxfd = __pts_master_listenfd;maxi = -1;FD_ZERO(&allset);FD_SET(__pts_master_listenfd, &allset);chmod(__PTS_UNSOCKET_PATH, 0777);while(1){readset = allset;nready = select(maxfd+1, &readset, NULL, &exceptset, NULL);if(nready <= 0){perror("select error");close(__pts_master_listenfd);unlink(__PTS_UNSOCKET_PATH);break;}if(FD_ISSET(__pts_master_listenfd, &readset)){len = sizeof(clt_addr);connfd = accept(__pts_master_listenfd, (struct sockaddr*)&clt_addr, &len);if(connfd < 0){perror("cannot accept client connect request.");close(__pts_master_listenfd);unlink(__PTS_UNSOCKET_PATH);break;}for(i=0; i<PTS_MAX_SLAVE; ++i){if(slaves[i].fd < 0){slaves[i].fd = connfd;break;}if(PTS_MAX_SLAVE == i){perror("too many connection.\n");exit(1);}}FD_SET(connfd, &allset);if(connfd > maxfd){maxfd = connfd;}if(i > maxi){maxi = i;}}for(i=0; i<=maxi; ++i){if((sockfd = slaves[i].fd ) < 0){continue;}if(FD_ISSET(sockfd, &readset)){   memset(msg, 0, STR_LEN);msglen = read(sockfd, msg, sizeof(msg));if(msglen < 0){close(sockfd);FD_CLR(sockfd, &allset);slaves[i].fd = -1;}int *magic = (int *)msg;if(*magic == PTS_MAGIC){memcpy(&slaves[i].ptsid, msg, sizeof(pts_tell));memcpy(&pts_tell, msg, sizeof(pts_tell));slave_connect_callback((struct pts_id*)&pts_tell, PTS_ON);struct pts_id tellpts;pts_get_id(&tellpts);write(sockfd, &tellpts, sizeof(tellpts)); }}//Exception fd peerif(FD_ISSET(sockfd, &exceptset)){if((sockfd = slaves[i].fd ) < 0){continue;}close(sockfd);FD_CLR(sockfd, &allset);memcpy(&pts_tell, &slaves[i].ptsid, sizeof(pts_tell));slave_connect_callback((struct pts_id*)&pts_tell, PTS_OFF);slaves[i].fd = -1;}}}close(__pts_master_listenfd);
}static int __pts_tell_unsocket_server(const char *unix_path)
{int __pts_master_listenfd, ret = -1;struct sockaddr_un srv_addr;__pts_master_listenfd = socket(AF_UNIX, SOCK_STREAM, 0);if(__pts_master_listenfd < 0){perror("sreate listening socket error.");return -1;}srv_addr.sun_family = AF_UNIX;strncpy(srv_addr.sun_path, unix_path, sizeof(srv_addr.sun_path)-1);ret = bind(__pts_master_listenfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));if(ret == -1){perror("cannot bind server socket.");close(__pts_master_listenfd);unlink(unix_path);return -1;}ret = listen(__pts_master_listenfd, 1);if(ret == -1){perror("cannot listen the client connect request.");close(__pts_master_listenfd);unlink(unix_path);return -1;}return __pts_master_listenfd;
}static int __pts_tell_unsocket_client(const char *unix_path)
{int connect_fd, ret = -1;struct sockaddr_un srv_addr;connect_fd = socket(AF_UNIX, SOCK_STREAM, 0);if(connect_fd < 0){perror("create socket error.");return -1;}srv_addr.sun_family = AF_UNIX;strcpy(srv_addr.sun_path, unix_path);ret = connect(connect_fd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));if(ret == -1){perror("connect error");close(connect_fd);return -1;}return connect_fd;
}static int ttysend(int fd, char *buf, size_t size)
{size_t i;for (i = 0; i < size; ++i)if (ioctl(fd, TIOCSTI, buf + i) == -1)return -1;return 0;
}int pts_print(struct pts_id *pts, char *fmt, ...)
{char pts_name[256] = {0};char line[1024] = {0};char echo[1100] = {0};int i;sprintf(pts_name, "%s/%d", PTS_PREFIX, pts->pts_dev_name);va_list va;va_start(va, fmt);int n = vsprintf(line, fmt, va);va_end(va);#if 0/***  作为terminal的输入*/int fd = open(pts_name, O_RDWR);ttysend(fd, line, strlen(line));close(fd);#elif 1/***  作为terminal的输出*/int fd = open(pts_name, O_RDWR);write(fd, line, strlen(line));close(fd);#else/***  直接印屏echo*/sprintf(echo, "echo \"%s\" > %s", line, pts_name);system(echo);#endifreturn n;
}

示例程序

master.c

#include <stdio.h>
#include "ptsTalk.h"int slaves_connect_callback(struct pts_id* slave_info, pts_stat stat)
{printf("Get a slave.\n");int i;for(i=0;i<3;i++){pts_print(slave_info, "Get a slave. %d\n", i);sleep(1);}return 0;
}int main()
{pts_master(&slaves_connect_callback);while(1){sleep(2);}return 0;
}

slave.c

#include <stdio.h>
#include "ptsTalk.h"int main()
{   struct pts_id master;pts_slave(&master);pts_print(&master, ">>>>>>>>>>>>>>>>>>>>>>>>>I got it.\n");while(1){sleep(2);}return 0;
}

makefile

LIBS+= ptsTalk/ptsTalk.c
INCLUDE+=-I ptsTalk
LIB+=-lm -pthread -lrtALL:gcc master.c -o master ${LIBS} ${LIB} ${INCLUDE}gcc slave.c -o slave ${LIBS} ${LIB} ${INCLUDE}clean:rm *~

效果:

Linux下的tty和pts:PTS之间标准输入输出的交互相关推荐

  1. Linux下的tty和pts详解

    Linux下的tty和pts详解 今天在在使用who和ps命令的时候,出现tty1或者pts/0,因为不太懂就查了一下: 使用tty命令可以查看现在使用的终端标识: 使用ctrl+alt+[F1~F8 ...

  2. LINUX下的tty,console与串口

    LINUX下的tty,console与串口 转载于:https://www.cnblogs.com/jingzhishen/p/6144880.html

  3. linux 什么是tty console和tty和串口的关系 如何在linux下查看tty对应哪个串口

    什么是TTY https://blog.csdn.net/goooooooooo/article/details/1302301?ops_request_misc=%257B%2522request% ...

  4. Linux下的tty和pts

    在使用who和ps命令的时候,有时会出现tty或者pts/1等. 使用tty命令可以查看现在使用的终端标识: 使用ctrl+alt+[F1~F8]来切换操作终端 使用echo "test x ...

  5. linux用户切换pts,Linux下的tty,pts,pty…和多窗口切换 | 云上小悟

    Linux下TTY(TeleType)的概念就是控制台终端的意思,TTY最初就是指那种老式的打字机. 如果你在vmware中安装ubuntu之后,你会发现有6个tty控制台可以用,通过Ctrl+Alt ...

  6. linux进程tty,linux下kill tty

    Linux下可以通过w命令或who命令查看当前登录的所有主机的pts信息,而非正常退出时,有时候pts并不会释放,这就会占用/dev/tty资源.如何将这种非正常退出的进程kill掉呢?当然,我们可以 ...

  7. LINUX下的tty,console与串口分析

    1.LINUX下TTY.CONSOLE.串口之间是怎样的层次关系?具体的函数接口是怎样的?串口是如何被调用的? 2.printk函数是把信息发送到控制台上吧?如何让PRINTK把信息通过串口送出?或者 ...

  8. linux 下一个 osw先从操作系统和标准脚本主动发起

    linux 下一个 osw与操作系统的引导和启动标准的脚本.osw它指的是--os watcher,这是一个显示器os这些指标shell脚本.osw监测数据一般使用oracle技能评估os资源的使用, ...

  9. linux的tty模式怎么用,Linux下的tty的使用

    1.查看机器目前所有的在运行的TTY [root@localhost ~]# w 05:49:15 up 23 min, 3 users, load average: 0.00, 0.04, 0.08 ...

最新文章

  1. C++ Primer 5th笔记(chap 16 模板和泛型编程)类模板部分特例化
  2. 全球及中国纳米材料行业竞争格局及发展规模预测报告2021年版
  3. Windows查看网络端口被占用情况netstat命令
  4. 错误:No plugin found for prefix spring-boot in the current project and in the plugin groups
  5. ddl hibernate_Hibernate:DDL模式生成
  6. 【操作系统】常见进程调度算法特点总结比较
  7. Linux 中 elasticsearch6.3.0 单机安装
  8. __clone class php_「PHP 技巧」 不要直接克隆对象,请使用深拷贝
  9. yii2 加载css,js
  10. eclipse清理无用import(一次性清理整个项目所有)
  11. python中line是什么意思_python 中循环 line for line in file(filename)什么意思?
  12. LearnOpenGL_study -- 平行光,点光源,聚光源
  13. 教你使用反格式化工具恢复格式化数据!
  14. 我喜欢计算机科学作文,我爱电脑作文9篇
  15. AC自动机模板(【CJOJ1435】)
  16. 计算机应用杂志-投稿经历
  17. sql 表和表之间关联
  18. “全量增量” 与 “增量同步” 一文了解清楚【建议收藏】
  19. Infrared and Visible Image Fusion using a Deep Learning Framework解析
  20. 技术总结-从输入 URL 到页面加载完成的过程中都发生了什么事情?

热门文章

  1. MAX31855 热电偶至数字输出转换器
  2. java数据结构- - - -栈
  3. Jmeter(一)http接口添加header和cookie
  4. wildfly-9.0.2 web项目部署详细步骤
  5. jQuery dataTables四种数据来源[转]-原文地址:http://xqqing79.iteye.com/blog/1219425
  6. [裴礼文数学分析中的典型问题与方法习题参考解答]5.1.16
  7. PHP:判断客户端是否使用代理服务器及其匿名级别
  8. 实现查询所有商品功能
  9. 2018mysql数据库面试题_面试题: mysql 数据库去重 已看1 不好使
  10. xp系统如何使两台计算机共享,xp系统共享文件,两部电脑共享文件方法