Menu
Woocommerce Menu

sed命令详解,打通linux的tty驱动的数据链路

0 Comment

 

 

 

Linux下的压缩和解压缩

  1. Sed简介 

一、首先把tty驱动在linux中的分层结构理清楚:

.tar.gz 用zip方式做的压缩包

    sed
是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern
space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有
改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。以下介绍的是Gnu版本的Sed
3.02。 

 

.tar.bz2 用bzip方式做的压缩包

    2. 定址 

图片 1

 

   
可以通过定址来定位你所希望编辑的行,该地址用数字构成,用逗号分隔的两个行数表示以这两行为起止的行的范围(包括行数表示的那两行)。如1,3表示1,2,3行,美元符号($)表示最后一行。范围可以通过数据,正则表达式或者二者结合的方式确定
。 

 

解压缩

     

 

.tar.gz

    3. Sed命令 

自上而下分为TTY核心层、TTY线路规程、TTY驱动。

tar -zxf 文件名解压缩

    调用sed命令有两种形式: 

 

-z zip方式

    * 

 

-x 解压缩

    sed [options] ‘command’ file(s) 

 

-f 名称

    * 

 

-C 把解压缩出来的东西另外放个目录

    sed [options] -f scriptfile file(s) 

二、TTY核心层与线路规程层分析

 

    a\ 

 

做个压缩包

    在当前行后面加入一行文本。 

用户空间的程序直接对tty核心层进行读写等相关操作,在tty_io.c中:

tar -zcf 文件名解压缩 被放入压缩包的目录

    b lable 

 

-z zip方式

    分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。 

int__init tty_init(void)

-c 创建压缩包

    c\ 

 

-f 名称

    用新的文本改变本行的文本。 

 

    d 

 

.tar.bz2

    从模板块(Pattern space)位置删除行。 

cdev_init(&tty_cdev,&tty_fops);

tar -jxf 文件名解压缩

    D 

 

-j bzip2方式

    删除模板块的第一行。 

if(cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||

-x 解压缩

    i\ 

 

-f 名称

    在当前行上面插入文本。 

register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, “/dev/tty”)< 0)

-C 把解压缩出来的东西另外放个目录

    h 

 

 

    拷贝模板块的内容到内存中的缓冲区。 

panic(“Couldn’tregister /dev/tty driver\n”);

做个压缩包

    H 

 

tar -jcf 文件名解压缩 被放入压缩包的目录

    追加模板块的内容到内存中的缓冲区 

device_create(tty_class,NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, “tty”);

-j bzip2方式

    g 

 

-c 创建压缩包

    获得内存缓冲区的内容,并替代当前模板块中的文本。 

……

-f 名称

    G 

 

 

    获得内存缓冲区的内容,并追加到当前模板块文本的后面。 

rpm是一种特殊的压缩包

    l 

 

-i 安装(在/目录下做解压缩等工作)

    列表不能打印字符的清单。 

 

-e 删除

    n 

 

-q 名称 查询名称是否被安装,如果什么都没有出来就表示没有装

    读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。 

 

-qa 查询已经安装到系统所有的软件包

    N 

以上的一段初始化代码可以获取以下信息:

-qf 查询某个文件或者目录来自哪个软件包

   
追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。 

 

 

    p 

注册了一个字符驱动,用户空间操作对应到tty_fops结构体里的函数:

源码软件的安装(一般步骤)

    打印模板块的行。 

 

1、下载软件

    P(大写) 

staticconst struct file_operations tty_fops = {

2、解压缩

    打印模板块的第一行。 

 

3、进入解压缩出来的目录

    q 

.llseek =no_llseek,

4、执行./configure 进行安装前检查和配置工作

    退出Sed。 

 

5、make 编译软件

    r file 

.read =tty_read,

6、make install 编译后安装

    从file中读行。 

 

 

    t label 

.write =tty_write,

 

   
if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。 

 

本文出自 “王道–旭忠著(MakeWong)” 博客

    T label 

.poll =tty_poll,

.tar.gz 用zip方式做的压缩包
.tar.bz2 用bzip方式做的压缩包 解压缩 .tar.gz tar -zxf 文件名解压缩 -z
zip方式 -x 解压缩 -f 名…

   
错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。 

 

    w file 

.unlocked_ioctl =tty_ioctl,

    写并追加模板块到file末尾。 

 

    W file 

.compat_ioctl =tty_compat_ioctl,

    写并追加模板块的第一行到file末尾。 

 

    ! 

.open =tty_open,

    表示后面的命令对所有没有被选定的行发生作用。 

 

    s/re/string 

.release =tty_release,

    用string替换正则表达式re。 

 

    = 

.fasync =tty_fasync,

    打印当前行号码。 

 

    # 

};

    把注释扩展到下一个换行符以前。 

 

    以下的是替换标记 

对于字符设备驱动,我们知道,读写操作一一对应于fops。

    * 

 

    g表示行内全面替换。 

 

    * 

 

    p表示打印行。 

 

    * 

tty_open:

    w表示把行写入一个文件。 

 

    * 

static int tty_open(struct inode *inode, struct file *filp)

    x表示互换模板块中的文本和缓冲区中的文本。 

 

    * 

    y表示把一个字符翻译为另外的字符(但是不用于正则表达式) 

 

     

int index;

    4. 选项 

 

    -e command, –expression=command 

dev_tdevice = inode->i_rdev;

    允许多台编辑。 

 

    -h, –help 

structtty_driver *driver;

    打印帮助,并显示bug列表的地址。 

 

    -n, –quiet, –silent 

……

     

 

    取消默认输出。 

driver= get_tty_driver(device, &index);

    -f, –filer=script-file 

 

    引导sed脚本文件名。 

……

    -V, –version 

 

    打印版本和版权信息。 

tty= tty_init_dev(driver, index, 0);

     

 

    5. 元字符集^ 

……

    锚定行的开始 如:/^sed/匹配所有以sed开头的行。  

 

    $ 

retval= tty_add_file(tty, filp);

    锚定行的结束 如:/sed$/匹配所有以sed结尾的行。  

 

    . 

……

    匹配一个非换行符的字符 如:/s.d/匹配s后接一个任意字符,然后是d。  

 

    * 

if(tty->ops->open)

    匹配零或多个字符
如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行。 

 

    []

retval= tty->ops->open(tty, filp);

    匹配一个指定范围内的字符,如/[Ss]ed/匹配sed和Sed。 

 

    [^]

   
匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。 

 

    \(..\)

 

    保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。 

 

    &

 

   
保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。  

get_tty_driver是根据设备号device,通过查找tty_drivers全局链表来查找tty_driver。

    \< 

 

    锚定单词的开始,如:/\<love/匹配包含以love开头的单词的行。  

tty_init_dev是初始化一个tty结构体:

    \> 

 

    锚定单词的结束,如/love\>/匹配包含以love结尾的单词的行。  

tty->driver= driver;

    x\{m\} 

 

    重复字符x,m次,如:/0\{5\}/匹配包含5个o的行。  

tty->ops= driver->ops;

    x\{m,\} 

 

    重复字符x,至少m次,如:/o\{5,\}/匹配至少有5个o的行。  

并建立线路规程:

    x\{m,n\} 

 

    重复字符x,至少m次,不多于n次,如:/o\{5,10\}/匹配5–10个o的行。 

ldops= tty_ldiscs[N_TTY];

    6. 实例 

 

    删除:d命令 

ld->ops= ldops;

    * 

 

    $ sed ‘2d’ example—–删除example文件的第二行。 

tty->ldisc= ld;

    * 

 

    $ sed ‘2,$d’ example—–删除example文件的第二行到末尾所有行。 

 

    * 

 

    $ sed ‘$d’ example—–删除example文件的最后一行。 

 

    * 

其实tty_ldiscs[N_TTY]在console_init中确定,该函数在内核启动的时候调用。

    $ sed ‘/test/’d example—–删除example文件所有包含test的行。 

 

    替换:s命令 

tty_register_ldisc(N_TTY,&tty_ldisc_N_TTY);

    * 

 

    $ sed ‘s/test/mytest/g’
example—–在整行范围内把test替换为mytest。如果没有g标记,则只有每行第一个匹配的test被替换成mytest。 

则:tty_ldiscs[N_TTY]=&tty_ldisc_N_TTY;

    * 

 

    $ sed -n ‘s/^test/mytest/p’
example—–(-n)选项和p标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的test被替换成mytest,就打印它。 

 

    * 

 

    $ sed ‘s/^192.168.0.1/&localhost/’
example—–&符号表示替换换字符串中被找到的部份。所有以192.168.0.1开头的行都会被替换成它自已加localhost,变成192.168.0.1localhost。 

 

    * 

struct tty_ldisc_ops tty_ldisc_N_TTY = {

    $ sed -n ‘s/\(love\)able/\1rs/p’
example—–love被标记为1,所有loveable会被替换成lovers,而且替换的行会被打印出来。 

 

    * 

.magic = TTY_LDISC_MAGIC,

    $ sed ‘s#10#100#g’
example—–不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,“#”在这里是分隔符,代替了默认的“/”分隔符。表示把所有10替换成100。 

 

    选定行的范围:逗号 

.name = “n_tty”,

    * 

 

    $ sed -n ‘/test/,/check/p’
example—–所有在模板test和check所确定的范围内的行都被打印。 

.open = n_tty_open,

    * 

 

    $ sed -n ‘5,/^test/p’
example—–打印从第五行开始到第一个包含以test开始的行之间的所有行。 

.close = n_tty_close,

    * 

 

    $ sed ‘/test/,/check/s/$/sed test/’
example—–对于模板test和west之间的行,每行的末尾用字符串sed
test替换。 

.flush_buffer = n_tty_flush_buffer,

    多点编辑:e命令 

 

    * 

.chars_in_buffer= n_tty_chars_in_buffer,

    $ sed -e ‘1,5d’ -e ‘s/test/check/’
example—–(-e)选项允许在同一行里执行多条命令。如例子所示,第一条命令删除1至5行,第二条命令用check替换test。命令的执
行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。 

 

    * 

.read = n_tty_read,

    $ sed –expression=’s/test/check/’ –expression=’/love/d’
example—–一个比-e更好的命令是–expression。它能给sed表达式赋值。 

 

    从文件读入:r命令 

.write = n_tty_write,

    * 

 

    $ sed ‘/test/r file’
example—–file里的内容被读进来,显示在与test匹配的行后面,如果匹配多行,则file的内容将显示在所有匹配行的下面。 

.ioctl = n_tty_ioctl,

    写入文件:w命令 

 

    * 

.set_termios = n_tty_set_termios,

    $ sed -n ‘/test/w file’
example—–在example中所有包含test的行都被写入file里。 

 

    追加命令:a命令 

.poll = n_tty_poll,

    * 

 

    $ sed ‘/^test/a\\—>this is a example’ example<—–‘this
is a example’被追加到以test开头的行后面,sed要求命令a后面有一个反斜杠。 

.receive_buf = n_tty_receive_buf,

    插入:i命令 

 

    $ sed ‘/test/i\\ 

.write_wakeup = n_tty_write_wakeup

    new line 

 

    ————————-‘ example 

};

    如果test被匹配,则把反斜杠后面的文本插入到匹配行的前面。 

 

    下一个:n命令 

tty_add_file主要是将tty保存到file的私有变量private_data中。

    * 

 

    $ sed ‘/test/{ n; s/aa/bb/; }’
example—–如果test被匹配,则移动到匹配行的下一行,替换这一行的aa,变为bb,并打印该行,然后继续。 

tty->ops->open的调用,实则上就是应用driver->ops->open。这样,我们就从tty核心层到tty驱动层了。

    变形:y命令 

 

    * 

 

    $ sed ‘1,10y/abcde/ABCDE/’
example—–把1–10行内所有abcde转变为大写,注意,正则表达式元字符不能使用这个命令。 

 

    退出:q命令 

 

    * 

tty_write:

    $ sed ’10q’ example—–打印完第10行后,退出sed。 

 

    保持和获取:h命令和G命令 

static ssize_t tty_write(struct file *file, const char __user
*buf,

    * 

 

    $ sed -e ‘/test/h’ -e ‘$G
example—–在sed处理文件的时候,每一行都被保存在一个叫模式空间的临时缓冲区中,除非行被删除或者输出被取消,否则所有被处理的行都将
打印在屏幕上。接着模式空间被清空,并存入新的一行等待处理。在这个例子里,匹配test的行被找到后,将存入模式空间,h命令将其复制并存入一个称为保
持缓存区的特殊缓冲区内。第二条语句的意思是,当到达最后一行后,G命令取出保持缓冲区的行,然后把它放回模式空间中,且追加到现在已经存在于模式空间中
的行的末尾。在这个例子中就是追加到最后一行。简单来说,任何包含test的行都被复制并追加到该文件的末尾。 

size_t count, loff_t *ppos)

    保持和互换:h命令和x命令 

 

    * 

{

    $ sed -e ‘/test/h’ -e ‘/check/x’ example
—–互换模式空间和保持缓冲区的内容。也就是把包含test与check的行互换。 

 

    7. 脚本 

……

   
Sed脚本是一个sed的命令清单,启动Sed时以-f选项引导脚本文件名。Sed对于脚本中输入的命令非常挑剔,在命令的末尾不能有任何空白或文本,如果在一行中有多个命令,要用分号分隔。以#开头的行为注释行,且不能跨行。

 

. Sed简介 sed
是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为模式空间(pattern
space),接着…

ld= tty_ldisc_ref_wait(tty);

 

if(!ld->ops->write)

 

ret= -EIO;

 

else

 

ret= do_tty_write(ld->ops->write, tty, file, buf, count);

 

……

 

}

 

从以上这个函数里,可以看到tty_write调用路线规程的write函数,所以,我们来看ldisc中的write函数是怎样的。经过一些操作后,最终调用:

 

tty->ops->flush_chars(tty);

 

tty->ops->write(tty,b, nr);

 

显然,这两个函数,都调用了tty_driver操作函数,因为在之前的tty_open函数中有了tty->ops=driver->ops这样的操作。那么这个tty_driver是怎样的呢,在TTY系统中,tty_driver是需要在驱动层注册的。注册的时候就初始化了ops,也就是说,接下来的事情要看tty_driver的了。

 

 

 

 

tty_read:

 

static ssize_t tty_read(struct file *file, char __user *buf,
size_t count,

标签:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图