zoukankan      html  css  js  c++  java
  • linux内核情景分析之命名管道

    管道是一种"无名","无形文件,只可以近亲进程使用,不可以再任意两个进程通信使用,所以只能实现"有名","有形"的文件来实现就可以克服其缺点,这里的有名:一个文件应该有文件名,使得任何进程可以通过文件名或者路径找到该文件,有形指的是文件的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) ", 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节点存在磁盘,但那只是一个节点,而文件的数据之存在内存缓冲区.与普通管道一样













  • 相关阅读:
    介绍自己
    第六周作业
    第五周作业
    第四周作业
    秋季学期学习总结
    币值转化
    justintime compiler
    PostgreSQL windows下安装出现问题的解决办法
    Java语言的异常处理,完全理解下面4点就可以了
    Ultraedit用途【来自网络】
  • 原文地址:https://www.cnblogs.com/zengyiwen/p/6003098.html
Copyright © 2011-2022 走看看