青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-162  評論-223  文章-30  trackbacks-0
引言
   在Unix的世界里,萬物皆文件,通過虛擬文件系統VFS,程序可以用標準的Unix系統調用對不同的文件系統,甚至不同介質上的文件系統進行讀寫操作。對于網絡套接字socket也是如此,除了專屬的Berkeley Sockets API,還支持一些標準的文件IO系統調用如read(v)、write(v)和close等。那么為什么socket也支持文件IO系統調用呢?在Linux上,這是通過套接口偽文件系統sockfs來實現的,因為sockfs實現了VFS中的4種主要對象:超級塊super block、索引節點inode、目錄項對象dentry和文件對象file,當執行文件IO系統調用時,VFS就將請求轉發給sockfs,而sockfs就調用特定的協議實現,層次結構如下圖:
   本文以linux 2.6.34實現為基礎,本篇闡述初始化和Socket創建兩部分的實現,下篇闡述Socket操作和銷毀兩部分的實現。

初始化
   在內核引導時初始化網絡子系統,進而調用sock_init,該函數主要步驟如下:創建inode緩存,注冊和裝載sockfs,定義在net/socket.c中。
1static int __init sock_init(void)
2{
3    
4    init_inodecache();
5    register_filesystem(&sock_fs_type);
6    sock_mnt = kern_mount(&sock_fs_type);
7    
8}
   
   創建inode緩存
   init_inodecache為socket_alloc對象創建SLAB緩存,名稱為sock_inode_cachep,socket_alloc定義在include/net/sock.h中。
1struct socket_alloc {
2    struct socket socket;
3    struct inode vfs_inode;
4}
;
   socket_alloc由socket和inode結構2部分組成,這樣就方便了在套接字與inode對象間雙向定位。

   注冊sockfs
   調用VFS的函數register_filesystem實現注冊,sock_fs_type定義在net/socket.c中。
1static struct file_system_type sock_fs_type = {
2    .name =        "sockfs",
3    .get_sb =    sockfs_get_sb,
4    .kill_sb =    kill_anon_super,
5}
;
   sock_fs_type包含了文件系統sockfs的名稱、創建和銷毀super block的函數,其中sockfs_get_sb實現在net/socket.c中。
1static int sockfs_get_sb(struct file_system_type *fs_type,int flags, const char *dev_name, void *data,struct vfsmount *mnt)
2{
3    return get_sb_pseudo(fs_type, "socket:"&sockfs_ops, SOCKFS_MAGIC, mnt);
4}
   它在kern_mount內被執行,通過調用get_sb_pseudo創建了一個super block(包含一個對應dentry及一個關聯inode):操作對象為sockfs_ops,根目錄名稱為socket:,對應的根索引節點編號為1。
   sockfs_ops定義在net/socket.c中。
1static const struct super_operations sockfs_ops = {
2    .alloc_inode =    sock_alloc_inode,
3    .destroy_inode = sock_destroy_inode,
4    .statfs =    simple_statfs,
5}
;
   sock_alloc_inode用于分配inode對象,將在socket創建過程中被調用;sock_destroy_inode用于釋放inode對象,將在socket銷毀過程中被調用;simple_statfs用于獲取sockfs文件系統的狀態信息。
   
   裝載sockfs
   由kern_mount函數實現裝載一個偽文件系統(當然,它沒有裝載點),返回一個static vfsmount對象sock_mnt。

   經過以上步驟后,所創建的VFS對象關系如下圖:
    對于根目錄項,不用進行路徑轉換,因此dentry的d_op為空(未畫出);對于偽文件系統,操作索引對象沒有意義,所以inode的i_op為空(未畫出)。

Socket創建


   系統調用socket、accept和socketpair是用戶空間創建socket的幾種方法,其核心調用鏈如下圖:
   從上圖可知共同的核心就3個過程:先構造inode,再構造對應的file,最后安裝file到當前進程中(即關聯映射到一個未用的文件描述符),下面就這3個過程進行詳細說明。

   構造inode
   由sock_alloc函數實現,定義在net/socket.c中。
 1static struct socket *sock_alloc(void)
 2{
 3    struct inode *inode;
 4    struct socket *sock;
 5
 6    inode = new_inode(sock_mnt->mnt_sb);
 7        
 8    sock = SOCKET_I(inode);
 9            
10    inode->i_mode = S_IFSOCK | S_IRWXUGO;
11    inode->i_uid = current_fsuid();
12    inode->i_gid = current_fsgid();
13        
14    return sock;
15}
   先調用new_inode創建inode對象,再設置它的類型為S_IFSOCK,由此可知inode對應的文件類型為套接字。new_inode是文件系統的一個接口函數,用于創建一個inode對象,定義在fs/inode.c中,它調用了sockfs超級塊的操作對象即sockfs_ops的sock_alloc_inode方法,由于sock_alloc_inode實際創建的是socket_alloc復合對象,因此要使用SOCKET_I宏從inode中取出關聯的socket對象用于返回。

   構造file
   有了inode對象后,接下來就要構造對應的file對象了,由sock_alloc_file實現,定義在net/socket.c中。
 1static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
 2{
 3    struct qstr name = { .name = "" };
 4    struct path path;
 5    struct file *file;
 6    int fd;
 7
 8    fd = get_unused_fd_flags(flags);
 9        
10    path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
11        
12    path.mnt = mntget(sock_mnt);
13
14    path.dentry->d_op = &sockfs_dentry_operations;
15    d_instantiate(path.dentry, SOCK_INODE(sock));
16    SOCK_INODE(sock)->i_fop = &socket_file_ops;
17
18    file = alloc_file(&path, FMODE_READ | FMODE_WRITE, &socket_file_ops);
19    
20    sock->file = file;
21    file->f_flags = O_RDWR | (flags & O_NONBLOCK);
22    file->f_pos = 0;
23    file->private_data = sock;
24
25    *= file;
26    return fd;
27}
   sock為上一過程返回的套接字對象,該函數主要做了以下幾件事:
   1)得到空閑的文件描述符fd,實際上就是fd數組的索引,準備作為返回值。
   2)先初始化路徑path:其目錄項的父目錄項為超級塊對應的根目錄,名稱為空,操作對象為sockfs_dentry_operations,對應的索引節點對象為sock套接字關聯的索引節點對象,即SOCK_INODE(sock);裝載點為sock_mnt。  
   sockfs_dentry_operations定義在net/socket.c中。
1static const struct dentry_operations sockfs_dentry_operations = {
2    .d_dname  = sockfs_dname,
3}
;
   sockfs_dname會被d_path調用,用于計算socket對象的目錄項名稱。
   3)設置索引節點的文件操作對象為socket_file_ops,定義在net/socket.c中。
1static const struct file_operations socket_file_ops = {
2    
3    .aio_read =    sock_aio_read,
4    .aio_write =    sock_aio_write,
5    
6    .open =        sock_no_open,    /* special open code to disallow open via /proc */
7    .release =    sock_close,
8    
9}
;
   4)調用alloc_file,以path和socket_file_ops為輸入參數,這樣返回得到的file便與sock的inode關聯上了,并且操作對象為socket_file_ops,最后設置到輸出參數f中。
   5)建立file與socket的一一映射關系。
   
   安裝file
   由fd_install實現,定義在fs/open.c中。
 1void fd_install(unsigned int fd, struct file *file)
 2{
 3    struct files_struct *files = current->files;
 4    struct fdtable *fdt;
 5    spin_lock(&files->file_lock);
 6    fdt = files_fdtable(files);
 7    BUG_ON(fdt->fd[fd] != NULL);
 8    rcu_assign_pointer(fdt->fd[fd], file);
 9    spin_unlock(&files->file_lock);
10}
   fd和file分別為上一過程返回的空閑文件描述符和文件對象,使RCU技術來設置file到當前進程的fd數組中。
 
   經過以上過程后,所創建的VFS對象關系圖如下
   fd為file*數組的索引而不是成員字段;vfsmount與初始化之VFS對象關系圖中的vfsmount是同一個對象,即sock_mnt;對于偽文件系統,操作索引對象沒有意義,所以inode的i_op為空(未畫出)。
posted on 2015-05-03 16:31 春秋十二月 閱讀(8709) 評論(0)  編輯 收藏 引用 所屬分類: Network
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲网在线观看| 欧美影院成人| 欧美一区二区三区久久精品| 欧美在线观看视频一区二区| 欧美日韩极品在线观看一区| 99精品视频免费观看视频| 欧美综合国产精品久久丁香| 亚洲免费成人av| 国产女主播视频一区二区| 久久久精品网| 欧美一区二区网站| 国产精品一区二区三区四区| 麻豆成人在线播放| 国产欧美日韩在线视频| 欧美成人乱码一区二区三区| 中日韩美女免费视频网址在线观看 | 久久影音先锋| 在线性视频日韩欧美| 亚洲第一在线视频| 国产毛片一区| 欧美午夜精品久久久久久久| 久久夜色精品一区| 亚洲午夜日本在线观看| 亚洲三级免费观看| 亚洲欧美日韩精品久久久久| 91久久精品美女高潮| 亚洲精品国精品久久99热| 亚洲福利视频一区| 国内精品久久久久影院色| 国产一区二区三区精品欧美日韩一区二区三区 | 国产精品日本一区二区| 你懂的一区二区| 欧美不卡一区| 久久综合国产精品台湾中文娱乐网| 久久精品一区二区三区中文字幕 | 免费亚洲一区二区| 久久国产精品毛片| 日韩视频在线观看免费| 一本色道久久综合一区| 在线亚洲伦理| av成人老司机| 久久欧美中文字幕| 亚洲精品老司机| 亚洲天堂第二页| 老鸭窝毛片一区二区三区 | 篠田优中文在线播放第一区| 亚洲人成77777在线观看网| 宅男精品视频| 亚洲欧美在线免费观看| 欧美 日韩 国产在线 | 国外视频精品毛片| 91久久综合亚洲鲁鲁五月天| 午夜一区二区三区不卡视频| 欧美成人国产| 在线视频一区二区| 久久免费精品日本久久中文字幕| 国产精品国产三级国产| 黄色一区二区在线观看| 午夜精品久久久久久久男人的天堂| 麻豆国产va免费精品高清在线| 亚洲视频专区在线| 午夜精品网站| 国产精品视频午夜| 亚洲精品国久久99热| 麻豆精品视频在线观看视频| 亚洲影院在线观看| 国产精品www994| 一区二区欧美亚洲| 亚洲精选视频在线| 久久久精品国产免大香伊| 欧美日韩在线视频一区二区| 在线日韩一区二区| 欧美sm极限捆绑bd| 亚洲欧美在线另类| 国产精品网站在线| 亚洲砖区区免费| 欧美成人a∨高清免费观看| 亚洲国产精品久久91精品| 美日韩精品免费观看视频| 欧美一区2区视频在线观看 | 亚洲国产日韩欧美综合久久 | 亚洲欧洲三级电影| 欧美不卡视频一区发布| 欧美不卡在线视频| 亚洲精品亚洲人成人网| 亚洲理论在线| 国产精品成人免费| 免费亚洲一区| 欧美成人免费播放| 亚洲午夜一二三区视频| 亚洲午夜久久久久久尤物| 国产精品久久午夜| 午夜精品在线视频| 欧美专区中文字幕| 亚洲国产日韩在线一区模特| 亚洲精品在线观看免费| 国产一区日韩一区| 亚洲乱码日产精品bd| 国产精品啊啊啊| 蜜桃av一区二区| 国产精品久久久久毛片大屁完整版| 久久久精品tv| 国产精品久久久久国产精品日日 | 国产一区二区三区日韩欧美| 免费久久99精品国产自| 欧美久久一区| 欧美成人第一页| 精品999在线观看| 欧美在线综合| 亚洲一级特黄| 久久精品在线观看| 一本大道av伊人久久综合| 欧美尤物巨大精品爽| 亚洲高清中文字幕| 久久国产精品一区二区| 欧美亚洲视频一区二区| 欧美电影美腿模特1979在线看| 久久久人成影片一区二区三区观看| 亚洲乱码国产乱码精品精| 亚洲一区二区免费看| 夜夜嗨av一区二区三区网页| 久久综合中文| 久久亚洲欧美国产精品乐播| 国产毛片久久| 日韩视频在线观看免费| 亚洲伦理网站| 国产精品久久久久久久久婷婷 | 午夜亚洲一区| 亚洲视频香蕉人妖| 欧美日韩第一页| 日韩亚洲不卡在线| 99在线|亚洲一区二区| 欧美mv日韩mv国产网站| 亚洲黄色精品| 午夜精品一区二区三区四区 | 狠狠综合久久av一区二区小说| 亚洲精品美女久久7777777| 伊人久久亚洲影院| 久久riav二区三区| 亚洲欧洲另类| 久久精品在线免费观看| 亚洲人成网站777色婷婷| 开心色5月久久精品| 亚洲经典在线| 欧美一区观看| 亚洲理论在线| 精品成人在线观看| 欧美顶级大胆免费视频| 欧美大片va欧美在线播放| 亚洲理论电影网| 国产亚洲欧洲| 国产精品国产三级国产普通话蜜臀| 久久精品国产清自在天天线 | 午夜天堂精品久久久久| 国产精品尤物| 可以免费看不卡的av网站| 国产麻豆精品视频| 欧美精品123区| 久久精品最新地址| 欧美一区二区三区四区夜夜大片| 亚洲人妖在线| 久久综合影视| 午夜精品美女自拍福到在线| 亚洲视频播放| 日韩一本二本av| 亚洲精品少妇| 亚洲精品在线视频观看| 国内自拍一区| 国内精品久久久久久| 国产精品国产一区二区| 欧美日本不卡视频| 欧美日韩精品在线观看| 欧美激情国产高清| 美女脱光内衣内裤视频久久影院| 欧美有码在线观看视频| 亚洲欧美中文在线视频| 亚洲欧美日韩精品久久久| 亚洲一区二区三区四区五区黄| 91久久极品少妇xxxxⅹ软件| 亚洲国产网站| 亚洲一级片在线看| 一本一本a久久| 欧美一区激情视频在线观看| 久久女同精品一区二区| 欧美激情精品久久久久久大尺度| 欧美日韩国产欧| 国产精品乱人伦一区二区| 国产精品视频免费在线观看| 国产日韩在线看| 国产精品久久久亚洲一区 | 欧美精品91| 欧美日韩精品一区视频 | 一区二区三区在线免费播放| 亚洲国产三级在线| 99re6这里只有精品| 亚洲在线黄色| 蜜桃伊人久久| 亚洲欧洲精品一区二区三区波多野1战4| 亚洲国产裸拍裸体视频在线观看乱了| 一本久道久久综合婷婷鲸鱼|