终端设备:设备文件

1. 终端设备

1.1 终端设备的设备号

  • 终端设备的主设备号是4,譬如:
    $ ls -l /dev/tty1
    $ crw–w---- 1 root tty 4, 1 Jan 8 19:48 /dev/tty1 [主设备号4,次设备号1]

    $ ls -l /dev/ttyS11
    crw-rw---- 1 root dialout 4, 75 Jan 8 19:48 /dev/ttyS11 [主设备号4,次设备号75]

1.2 打开终端设备作为控制终端

贴上一段内核代码:


		if (!(flag & O_NOCTTY) &&
		    current->leader &&
		    current->tty<0 &&
		    tty->session==0) {
			current->tty = min;
			tty->session= current->session;
			tty->pgrp = current->pgrp;
		}

可见,一个进程想打开一个终端设备作为控制终端的约束条件

  • 进程为会话首领
  • 进程原来没有控制终端
  • 指定的终端设备并没有被其它会话用作控制终端

2. [伪]终端设备

原则:
伪终端设备都成对存在 [主设备+从设备]

实现:
不同种类的操作系统,其伪终端接口大不相同。本节描述的代码基于Ubuntu 19.04

主设备文件:/dev/ptmx
$ ls -l /dev/ptmx
$ crw-rw-rw- 1 root tty 5, 2 Jan 9 01:34 /dev/ptmx 【设备号:5,2】

从设备文件:/dev/pts/*
$ ls -l /dev/pts/*
crw–w---- 1 jianleya tty 136, 0 Jan 8 19:48 0 【设备号:136,0】
crw–w---- 1 jianleya tty 136, 1 Jan 8 20:56 1
crw–w---- 1 jianleya tty 136, 10 Jan 8 19:48 10
crw–w---- 1 jianleya tty 136, 11 Jan 8 19:48 11

2.1 伪终端设备接口

01)打开pts主设备,同时在/dev/pts下创建一个pts从设备

       #include <stdlib.h>
       #include <fcntl.h>

       int posix_openpt(int flags);
       
       CONFORMING TO
       POSIX.1-2001, POSIX.1-2008.

02)打开伪终端 从设备

 Before opening the pseudoterminal  slave,  you  must  pass  the  master's  file  descriptor  to
 grantpt(3) and unlockpt(3).
       
首先:grantpt : grant access to the slave pseudoterminal
     #include <stdlib.h>

       int grantpt(int fd);
       CONFORMING TO
       POSIX.1-2001, POSIX.1-2008.

其次:unlockpt      
       #include <stdlib.h>
       int unlockpt(int fd);
	   CONFORMING TO
       POSIX.1-2001, POSIX.1-2008.

再后:ptsname 获取从设备名称
#include <stdlib.h>
 char *ptsname(int fd);
POSIX.1-2001, POSIX.1-2008.

最后:打开从设备文件
调用open函数可读可写,即可!

2.2 打开伪终端设备作为控制终端

参考如下过程:编码
在这里插入图片描述
示例代码
父进程打印出从子进程递送过来的从终端设备名:

输出:
/dev/pts/17

#include <iostream>
#include <string>
using namespace std;

extern "C"
{
	#include <stdlib.h>
	#include <fcntl.h>
	#include <unistd.h>
	#include <stdio.h>
	#include <sys/types.h>
	#include <sys/wait.h>
}

int main(void)
{
	int fdm = posix_openpt(O_RDWR);
	if(-1 == fdm)
	{
		cout << "open master pts devices failed" << endl;
		return -1;
	}


	int res = grantpt(fdm);
	if(-1 == res)
	{
		cout << "grant slave pts device failed" << endl;
		return -1;
	}

	res  = unlockpt(fdm);
	if(-1 == res)
	{
		cout <<"unlock slave pts device failed" << endl;
		return -1;
	}

	pid_t pid  =fork();
	
	if(-1 == pid)
	{
		cout << "fork failed" << endl;
		return -1;
	}
	else if(0 == pid)
	{
		/*child process*/
		int res = setsid();
		if(-1 == res)
		{
			cout << "setsid failed" << endl;
			return -1;
		}

		char *ps_str = ptsname(fdm);
		if(NULL==ps_str)
		{
			cout << "get slave pts device name failed" << endl;
			return -1;
		}
		
		int fds=open(ps_str,O_RDWR);
		if(-1 == fds)
		{
			cout << "open slave pts device failed" << endl;
			return -1;
		}

		res = dup2(fds,STDIN_FILENO);
		if(-1==res)
		{
			cout << "child: dup2 stdin failed" << endl;
			return -1;
		}
		res=dup2(fds,STDOUT_FILENO);
		if(-1==res)
		{
			cout << "child: dup2 stdout failed" << endl;
			return -1;
		}	
		
		cout << ttyname(STDIN_FILENO) << endl;
	}
	else
	{
		/*father process*/

		/*comunicate with slave pts device*/
		res = dup2(fdm,STDIN_FILENO);
		if(-1==res)
		{
			cout << "dup2 stdin failed" << endl;
			return -1;
		}

	
		string said_something;
		
		cin >> said_something;
		cout << said_something << endl;

		int status = 0;

		int res = waitpid(pid,&status,0);
		if(-1 == res)
		{
			cout << "wait failed" << endl;
			return -1;
		}

	}
	
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值