Chinaunix首页 | 论坛 | 博客
  • 博客访问: 690461
  • 博文数量: 192
  • 博客积分: 1875
  • 博客等级: 上尉
  • 技术积分: 2177
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-23 23:21
个人简介

有时候,就是想窥视一下不知道的东东,因为好奇!

文章分类

全部博文(192)

文章存档

2024年(8)

2023年(3)

2020年(1)

2019年(1)

2018年(1)

2017年(2)

2016年(69)

2015年(53)

2014年(14)

2013年(1)

2012年(5)

2011年(25)

2010年(9)

分类: LINUX

2016-10-18 23:16:07

内核资料收集

1. FiFO
        pipe管道一个主要的缺点, 无法打开已经存在的pipe管道. 只能在有共同祖先的进程之间使用. 这使pipe管道的使用受到限制.
    例如, 有一个数据库引擎服务器, 该服务器连续地轮流询问发出查询请求的客户端进程, 并把数据库查询的结果返回客户端进程. 
    服务器和给定客户之间的每次交互都可以使用一个管道进行处理. 但是,当用户显式查询数据库时, 通常由shell命令根据需要创建
    客户端进程; 因此,服务器进程和客户端进程就不能方便地共享管道.
        为了突破这种限制, unix系统引入了一种称为命名管道(named pipe)或者FIFO(first in ,first out: 先进先出. 最先写入的字节总是
    最先读出)的特殊文件类型. FIFO在这几个方面都类似于管道: 在文件系统中不拥有磁盘块, 打开的FIFO总是与一个内核缓冲区
    相关联, 这个缓冲区中临时存放两个或多个进程之间交换的数据.

        有了磁盘索引节点,使得任何进程都可以访问FIFO, 因为FIFO文件名包含在系统的目录树中.因此,在前面那个数据库的例子中,服务
    器和客户端之间的通信可以很容易地使用FIFO而不是管道. 服务器在启动时创建一个FIFO, 由客户端程序用来发出自己的请求.每
    个客户程序在建立连接之前都另外创建一个FIFO, 并在自己对服务器发出的最初请求中包含这个FIFO的名字, 服务器程序就可以
    把查询结果写入这个FIFO.

        linux2.6的FIFO和管道几乎是相同的,并使用相同的pipe_inode_info结构. 事实上, FIFO的read和write操作和管道的操作相同, 
    只有两点主要差别:
            a. FIFO索引节点出现在系统目录树上,而不是pipefs特殊文件系统中
            b. FIFO是一种双向通信管道; 也就是说可能以读/写模式打开一个FIFO.

2. 创建并打开FIFO
        进程通过执行mknod()系统调用创建一个FIFO, 传递的参数是新FIFO的路径名及S_IFIFO与这个新文件的权限位掩码进行逻辑或
    的结果. POSIX引入mkfifo()专门用来创建FIFO. FIFO一旦被创建,就可以使用普通的open()/read()/write()/close()系统调用访问FIFO.     FIFO的索引节点及文件操作都是专用的,并且不依赖于FIFO所在的文件系统. 
        POSIX标准定义了open()系统调用对FIFO的操作; 这种操作本质上与所有请求的访问类型, I/O操作的种类以及其它正在访问
    FIFO的进程的存在状况有关. 
        进程可以为读操作/写操作或者读写操作打开一个FIFO.根据这三种情况,把与相应的文件对象相关的文件操作设置成特定的方法.
    当进程打开一个FIFO的时, VFS就执行一些与设备文件所执行的操作相同的操作. 与打开的FIFO相关的索引节点对象是由依赖于
    文件系统的read_inode超级块方法进行初始化的. 这个方法总要检查磁盘上的索引节点是否表示一个特殊文件,并在必要时调用    
    init_special_inode()函数. 这个函数又把索引节点对象i_ops字段设置为def_fifo_fops表的地址.随后,内核把文件系统对象的文件操作
    表设置为def_fifo_fops, 并执行它的open方法, 这个方法由fifo_open实现.

    fifo_open函数初始化专用于FIFO的数据结构; 具体来说,它执行下列操作:
            a. 获取i_sem索引节点信号量
            b. 检查索引节点对象的i_pipe字段; 如果为NULL,则分配并初始化一个新的pipe_inode_info结构. 
            c. 根据open系统调用的参数中指定的访问模式, 用合适的文件操作表的地址初始化文件对象的f_op字段. 如下表
                    
            d. 如果访问模式或者为只读模式或者为读/写模式, 则把1加到pipe_inode_info结构的readers字段和r_counter字段. 此外,如果
                访问模式只读, 且没有其它的读进程,则唤醒等待队列上的任何写进程.
            e. 如果访问模式或者为只写模式或者为读/写模式, 则把1加到pipe_inode_info结构的writers字段和w_counter字段. 此外,如果
                访问模式只写 , 且没有其它的写进程,则唤醒等待队列上的任何读进程.
            f. 如果没有读进程或没有写进程,则确定函数是应当阻塞还是返回一个错误码而终止. 如下表
                    
            g. 释放索引节点信号量,并终止, 返回0.


            FIFO的三个文件操作表项的主要区别是read和write方法的实现不同. 如果访问类型允许读操作, 那么read方法是使用
        pipe_read()函数实现的; 否则,read()方法就用bad_pipe_r()函数实现, 该函数只是返回一个错误码. 类似的,如果访问类型
        允许写操作,那么write方法就是用pipe_write()函数实现的; 否则write方法就是用bad_pipe_w()函数实现,该函数也只是返回一个
        错误代码.

阅读(867) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~