搜尋此網誌

2011年7月31日 星期日

tcpip stack(1) -- init

1. socket_init()建立vfsmount文件系统
static struct vfsmount *sock_mnt __read_mostly;
static int __init sock_init(void)
{
    skb_init(); //为socket buffer创建高速缓存
    init_inodecache(); //为struct sock_alloc创建高速缓存

    //创建已安装文件系统
    register_filesystem(&sock_fs_type);
    sock_mnt = kern_mount(&sock_fs_type);
}

static struct file_system_type sock_fs_type = {
    .name = "sockfs",
    .mount = sockfs_mount,
    .kill_sb = kill_anon_super,
};

static struct file_system_type *file_systems;
int register_filesystem(struct file_system_type * fs)
{
    struct file_system_type ** p;
    /*将sock_fs_type注册到全局的file_systems中*/
    p = find_filesystem(fs->name, strlen(fs->name));
    if(p)
        return error;
    else
        *p = fs;
}

函数kern_mount()将调用vfs_kern_mount()创建vfsmount
struct vfsmount *
vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
    struct vfsmount *mnt;
    struct dentry *root;

    mnt = alloc_vfsmnt(name); //从高速缓存中获取vsfmount结构
    root = mount_fs(type, flags, name, data);

    //建立vfsmount与dentry的对应关系
    mnt->mnt_root = root;
    mnt->mnt_sb = root->d_sb;
    mnt->mnt_mountpoint = mnt->mnt_root;
    mnt->mnt_parent = mnt;
    return mnt;
}

创建dentry对象
struct dentry *
mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
{
    struct dentry *root;
    struct super_block *sb;

    root = type->mount(type, flags, name, data); //调用sock_fs_type中的sockfs_mount()
    sb = root->d_sb;

    return root;
}
sockfs_mount()将调用mount_pseudo()
static const struct super_operations sockfs_ops = {
    .alloc_inode = sock_alloc_inode,
    .destroy_inode = sock_destroy_inode,
    .statfs = simple_statfs,
};
static const struct dentry_operations sockfs_dentry_operations = {
    .d_dname = sockfs_dname,
};
struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
const struct super_operations *ops,
const struct dentry_operations *dops, unsigned long magic)
{
    struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
    //创建super block并注册到全局super_blocks中
    struct dentry *dentry;
    struct inode *root;

    root = new_inode(s); //创建inode对象
    dentry = d_alloc(NULL, &d_name); //创建dentry对象

    //将创建的3个对象建立联系
    ……
    return dentry;
}
初始化完成后:sock_mnt->vfsmount->dentry->inode->superblock
2. inet_init()网络网络层初始化
static int __init inet_init(void)
{
    proto_register(/*tcp, udp, raw*/); //将inet socket结构proto注册到proto_list中

    sock_register(&inet_family_ops); //将协议族net_proto_family注册到net_families中

    inet_add_protocol(/*tcp, udp, icmp*/);
    //将协议处理接口结构net_protocol注册到inet_protos中

    //建立inetsw链表与inetsw_array数组的对应关系
    for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)
        INIT_LIST_HEAD(r);
    for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)
        inet_register_protosw(q);
    ……
}
Socket基本结构:

3. socket()
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{
    struct socket *sock;
    /*调用sock_alloc创建struct socket_alloc,其中包含struct socket和struct inode;
     调用sock->create()-------->inet_create()创建struct sock
    */
    retval = sock_create(family, type, protocol, &sock);
    //创建文件描述符struct file,将file指针放入fd数组中
    retval = sock_map_fd(sock,flags&(O_CLOEXEC|O_NONBLOCK));
    return retval;
}
结构如图:
                                             struct socket_alloc
                                                    |-------------|
                                                    |  socket    |------>sock
                                                    |-------------|
                                 |----dentry->|   inode    |------------>
      Struct file->path-|                   |-------------|                  Super_block
                                 |----fsmount->dentry->inode------>

用户进程通过文件描述符就可以找到INET socket。BSD socket层从已注册的INET proto_ops结构中调用INET层socket支持例程来执行工作。例如,一个ipv4的BSD socket建立请求,将用到下层的INET socket的建立函数。为了不把BSD socket与tcpip的特定信息搞混,INET socket层使用它自己的数据结构struct sock,它与BSD socket结构相连。Sock结构的协议操作指针也在初始化时建立,它依赖于被请求的协议。如果请求时TCP,那么sock结构的协议操作指针将指向TCP连接所必须的TCP协议操作集。
4. net_dev_ini ()网络设备抽象层初始化
static int __init net_dev_init(void)
{
    //Initialise the packet receive queues.
    for (i = 0; i < NR_CPUS; i++) {
        struct softnet_data *queue; queue = &per_cpu(softnet_data, i);
        skb_queue_head_init(&queue->input_pkt_queue);

        queue->throttle = 0;
        queue->cng_level = 0;
        queue->avg_blog = 10; /* arbitrary non-zero */
        queue->completion_queue = NULL;
        INIT_LIST_HEAD(&queue->poll_list);
        set_bit(__LINK_STATE_START, &queue->backlog_dev.state);
        queue->backlog_dev.weight = weight_p;
        queue->backlog_dev.poll = process_backlog;
        atomic_set(&queue->backlog_dev.refcnt, 1);
    }

    open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
    open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
}
为每个CPU创建一个struct softnet_data的队列,表示要交给此CPU处理的数据包。并注册网络相关的软中断。
网络设备抽象层通过struct net_device调用指定的device driver与设备通信。
5. device driver initialize
用insmod加载驱动模块时,内核会默认执行模块中的module_init()函数
static int __init xxx_init_module (void)
{
    return pci_register_driver(&xxx_pci_driver);
}
module_init(xxx_init_module);

pci_register_driver()注册设备驱动程序(struct pci_driver)
int __pci_register_driver(struct pci_driver *drv, struct module *owner,
const char *mod_name)
{
    /*将strcut pci_driver加到总线链表中,并执行.probe()初始化设备驱动 */
    driver_register(&drv->driver);

    /* 为驱动创建sysfs文件 */
    pci_create_newid_file(drv);
    pci_create_removeid_file(drv);
}
strcut pci_driver->probe()调用驱动初始化函数初始化struct net_device
static int __devinit xxx_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
    struct net_device *dev = NULL;
    xxx_init_board (pdev, &dev);
    /* 设备抽象层提供驱动操作函数 */
    dev->open = xxx_open;
    dev->hard_start_xmit =xxx_start_xmit;
    dev->poll = xxx_poll;
    dev->stop = xxx_close;
    dev->do_ioctl = netdev_ioctl;
}

沒有留言:

張貼留言