管道是一种"无名","无形文件,只可以近亲进程使用,不可以再任意两个进程通信使用,所以只能实现"有名","有形"的文件来实现就可以克服其缺点,这里的有名:一个文件应该有文件名,使得任何进程可以通过文件名或者路径找到该文件,有形指的是文件的inode应该存在与磁盘或者其他文件熊截止上.使得任何进程可以再任何时间都可以建立联系.

命名管道的创建用mknod,当然也可以使用mknod函数创建命名管道.建立了这样的节点,进程就可以通过打开一个文件一样打开整个民命管道.

命名管道与匿名管道的不同之处仅仅在于打开的过程,分析如何通过open系统调用与filfo文件取得联系.进程在内核通过sys_open进入filp_open(),然后在open_namei()调用一个函数path_walk(),根据文件的路径在文件系统中找到代表这文件的inode,将磁盘的inode读取内存,根据文件类型,将inode的i_op和i_fop指针设置为对应的inode_operation与file_operation,但对于FIFO这样特殊的文件则用调用init_special_inode加以初始化,可见文件类型不属于ACL或者数据,不是普通文件,不是目录,不是符号连接,就属于FIFO文件
  1. if (inode->i_ino == EXT2_ACL_IDX_INO ||
  2. inode->i_ino == EXT2_ACL_DATA_INO)
  3. /* Nothing to do */ ;
  4. else if (S_ISREG(inode->i_mode)) {
  5. inode->i_op = &ext2_file_inode_operations;
  6. inode->i_fop = &ext2_file_operations;
  7. inode->i_mapping->a_ops = &ext2_aops;
  8. } else if (S_ISDIR(inode->i_mode)) {
  9. inode->i_op = &ext2_dir_inode_operations;
  10. inode->i_fop = &ext2_dir_operations;
  11. } else if (S_ISLNK(inode->i_mode)) {
  12. if (!inode->i_blocks)
  13. inode->i_op = &ext2_fast_symlink_inode_operations;
  14. else {
  15. inode->i_op = &page_symlink_inode_operations;
  16. inode->i_mapping->a_ops = &ext2_aops;
  17. }
  18. } else
  19. init_special_inode(inode, inode->i_mode,
  20. le32_to_cpu(raw_inode->i_block[0]));
接下来查看init_special_inode
  1. void init_special_inode(struct inode *inode, umode_t mode, int rdev)
  2. {
  3. inode->i_mode = mode;
  4. if (S_ISCHR(mode)) {
  5. inode->i_fop = &def_chr_fops;
  6. inode->i_rdev = to_kdev_t(rdev);
  7. } else if (S_ISBLK(mode)) {
  8. inode->i_fop = &def_blk_fops;
  9. inode->i_rdev = to_kdev_t(rdev);
  10. inode->i_bdev = bdget(rdev);
  11. } else if (S_ISFIFO(mode))//是fifo文件,设置文件操作为def_fifo_fops
  12. inode->i_fop = &def_fifo_fops;
  13. else if (S_ISSOCK(mode))
  14. inode->i_fop = &bad_sock_fops;
  15. else
  16. printk(KERN_DEBUG "init_special_inode: bogus imode (%o)\n", mode);
  17. }

  1. /*
  2. * Dummy default file-operations: the only thing this does
  3. * is contain the open that then fills in the correct operations
  4. * depending on the access mode of the file...
  5. */
  6. struct file_operations def_fifo_fops = {
  7. open: fifo_open, /* will set read or write pipe_fops */
  8. };
sys_open->filp_open->dentry_open->fifo_open()
  1. static int fifo_open(struct inode *inode, struct file *filp)
  2. {
  3. int ret;
  4. ret = -ERESTARTSYS;
  5. lock_kernel();
  6. if (down_interruptible(PIPE_SEM(*inode)))
  7. goto err_nolock_nocleanup;
  8. if (!inode->i_pipe) {//第一次打开fifo文件,该管道的缓冲页面没分配,以后打开会跳过
  9. ret = -ENOMEM;
  10. if(!pipe_new(inode))
  11. goto err_nocleanup;
  12. }
  13. filp->f_version = 0;
  14. switch (filp->f_mode) {
  15. case 1:
  16. /* //只读
  17. * O_RDONLY
  18. * POSIX.1 says that O_NONBLOCK means return with the FIFO
  19. * opened, even when there is no process writing the FIFO.
  20. */
  21. filp->f_op = &read_fifo_fops;
  22. PIPE_RCOUNTER(*inode)++;//读端的记录++
  23. if (PIPE_READERS(*inode)++ == 0)//表示刚打开读端,很可能有写进程睡眠,那就要唤醒写进程
  24. wake_up_partner(inode);
  25. if (!PIPE_WRITERS(*inode)) {//如果不存在写端
  26. if ((filp->f_flags & O_NONBLOCK)) {//并且不阻塞
  27. /* suppress POLLHUP until we have
  28. * seen a writer */
  29. filp->f_version = PIPE_WCOUNTER(*inode);//写端计数
  30. } else //不存在写端并且阻塞,那就之产生一般,需要睡眠,等待生产者进程将其唤醒
  31. {
  32. wait_for_partner(inode, &PIPE_WCOUNTER(*inode));
  33. if(signal_pending(current))
  34. goto err_rd;
  35. }
  36. }
  37. break;
  38. case 2:
  39. /*只写
  40. * O_WRONLY
  41. * POSIX.1 says that O_NONBLOCK means return -1 with
  42. * errno=ENXIO when there is no process reading the FIFO.
  43. *///不存在读端并且设置了不阻塞,直接return错误
  44. ret = -ENXIO;
  45. if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode))
  46. goto err;
  47. filp->f_op = &write_fifo_fops;//设置专用写操作
  48. PIPE_WCOUNTER(*inode)++;
  49. if (!PIPE_WRITERS(*inode)++)//如果写端第一次创建,很可能有读进程在睡眠
  50. wake_up_partner(inode);//将其唤醒
  51. if (!PIPE_READERS(*inode)) {//如果不存在读端并且阻塞
  52. wait_for_partner(inode, &PIPE_RCOUNTER(*inode));//休眠等待读进程将其唤醒
  53. if (signal_pending(current))
  54. goto err_wr;
  55. }
  56. break;
  57. case 3:
  58. /*可读可写
  59. * O_RDWR
  60. * POSIX.1 leaves this case "undefined" when O_NONBLOCK is set.
  61. * This implementation will NEVER block on a O_RDWR open, since
  62. * the process can at least talk to itself.
  63. *///相当于一个进程同时打开命名管道的两端,所以不需要等待,只要任何一端是第一次打开,就唤醒在睡眠的进程
  64. filp->f_op = &rdwr_fifo_fops;
  65. PIPE_READERS(*inode)++;
  66. PIPE_WRITERS(*inode)++;
  67. PIPE_RCOUNTER(*inode)++;
  68. PIPE_WCOUNTER(*inode)++;
  69. if (PIPE_READERS(*inode) == 1 || PIPE_WRITERS(*inode) == 1)
  70. wake_up_partner(inode);
  71. break;
  72. default:
  73. ret = -EINVAL;
  74. goto err;
  75. }
  76. /* Ok! */
  77. up(PIPE_SEM(*inode));
  78. unlock_kernel();
  79. return 0;
  80. err_rd:
  81. if (!--PIPE_READERS(*inode))
  82. wake_up_interruptible(PIPE_WAIT(*inode));
  83. ret = -ERESTARTSYS;
  84. goto err;
  85. err_wr:
  86. if (!--PIPE_WRITERS(*inode))
  87. wake_up_interruptible(PIPE_WAIT(*inode));
  88. ret = -ERESTARTSYS;
  89. goto err;
  90. err:
  91. if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) {
  92. struct pipe_inode_info *info = inode->i_pipe;
  93. inode->i_pipe = NULL;
  94. free_page((unsigned long)info->base);
  95. kfree(info);
  96. }
  97. err_nocleanup:
  98. up(PIPE_SEM(*inode));
  99. err_nolock_nocleanup:
  100. unlock_kernel();
  101. return ret;
  102. }
注意FIFO文件的inode节点存在磁盘,但那只是一个节点,而文件的数据之存在内存缓冲区.与普通管道一样









linux内核情景分析之命名管道的更多相关文章

  1. linux内核情景分析之匿名管道

    管道的机制由pipe()创建,由pipe()所建立的管道两端都在同一进程.所以必须在fork的配合下,才可以在具有亲缘关系的进程通信 /* * sys_pipe() is the normal C c ...

  2. linux内核情景分析之execve()

    用来描述用户态的cpu寄存器在内核栈中保存情况.可以获取用户空间的信息 struct pt_regs { long ebx; //可执行文件路径的指针(regs.ebx中 long ecx; //命令 ...

  3. Linux内核情景分析之消息队列

    早期的Unix通信只有管道与信号,管道的缺点: 所载送的信息是无格式的字节流,不知道分界线在哪,也没通信规范,另外缺乏控制手段,比如保温优先级,管道机制的大小只有1页,管道很容易写满而读取没有及时,发 ...

  4. Linux内核情景分析的alloc_pages

    NUMA结构的alloc_pages ==================== mm/numa.c 43 43 ==================== 43 #ifdef CONFIG_DISCON ...

  5. Linux内核情景分析之异常访问,用户堆栈的扩展

    情景假设: 在堆内存中申请了一块内存,然后释放掉该内存,然后再去访问这块内存.也就是所说的野指针访问. 当cpu产生页面错误时,会把失败的线性地址放在cr2寄存器.线性地址缺页异常的4种情况 1.如果 ...

  6. linux内核情景分析之exit与Wait

    //第一层系统调用 asmlinkage long sys_exit(int error_code) { do_exit((error_code&0xff)<<8); } 其主体是 ...

  7. linux内核情景分析之内核中的互斥操作

    信号量机制: struct sempahore是其结构,定义如下 struct semaphore { atomic_t count;//资源数目 int sleepers;//等待进程数目 wait ...

  8. linux内核情景分析之信号实现

    信号在进程间通信是异步的,每个进程的task_struct结构有一个sig指针,指向一个signal_struct结构 定义如下 struct signal_struct { atomic_t cou ...

  9. linux内核情景分析之强制性调度

    从系统调用返回到用户空间是否调度,从ret_with_reschedule可看出,是否真正调度,取决于当前进程的pcb中的need_resched是否设置为1,那如何设置为1取决于以下几种情况: 时间 ...

随机推荐

  1. 作业hashlib题目

    '''1.编写用户认证功能,要求如下 1.1.对用户密码加盐处理 1.2.用户名与密文密码存成字典,是以json格式存到文件中的 1.3.要求密用户输入明文密码,但程序中验证的是密文'''import ...

  2. 如何修改iframe内的页面的元素的样式。。。。

    方法一: 直接通过设置backgroundColor的颜色即可:<!DOCTYPE html><html><head><script>function ...

  3. Android Studio 3.0 安装注意点

    在安装Android studio 3.0+ 时候,会遇到默认不带Android SDK 的问题. 在启动Android studio 后,会提示让选择SDK目录,选择下载目录,对应的去下载 那么问题 ...

  4. pandas知识点(基本功能)

    1.重新索引 如果reindex会根据新索引重新排序,不存在的则引入缺省: In [3]: obj = Series([4.5,7.2,-5.3,3.6], index=["d", ...

  5. 服务器常说的U是什么意思?

    U是英文单词:unit 所说的1U和2U,是服务器的厚度,1U大概是相当于机柜的两个小格子,2U是四个格子.1U大概是4.45厘米(1U=1.75英寸,1英寸=2.54CM).以下这个是图片:

  6. centos6.9系统安装

    1. 选择系统及下载 CentOS 5.x CentOS 6.x 50% 6.9 CentOS 7.x 50% 7.2 centos 6.9 centos 7. 最新版 https://wiki.ce ...

  7. mysql进阶三四五六

    排序查询 一.语法 select 查询表 from 表 where 筛选条件 order by 排序列表[asc / desc] 特点: 1.asc:升序 desc:降序 2.排序列表之中支持单字段, ...

  8. 浅谈I/O模型

    在学习线程,NIO等知识时都需要知道一些基础知识. 一.什么是同步或异步 同步:个人通俗理解多个人排队打饭一个窗口,只有前面一个人打完了,后面的人才能打.如果前面人因为什么原因一直站在那里不走,后面的 ...

  9. loj2051 「HNOI2016」序列

    ref #include <algorithm> #include <iostream> #include <cstdio> #include <cmath& ...

  10. Asp.net自定义控件开发任我行(7)-注册自定义事件

    摘要 前面我们已经把嵌入资源讲完了,不知道大家有没有得到收益,本章主要讲自定义事件,也就是给TextBox注册一个点击事件. 引言 不知道道上的朋友有没有注意到TextBox控件没有点击事件,就连网上 ...