• socket:内核初始化及创建流(文件)详细过程


    socket中文名称为套接字,属于传输协议及功能接口的封装。socket首先初始化注册(socket)文件系统,然后由使用它的模块传入具体的地址族(类型)family,如ipv4模块中的(void)sock_register(&inet_family_ops);
    当调用者执行socket()函数时,会触发__sys_socket函数,完成socket文件的创建、修改模式为流模式、提供文件系统操作结构的功能接口、SELINUX策略绑定等等。

    目录


    1. 源码流程

    1.1 sock_init

    1.2 socket文件创建

    2. 源码结构

    3. 部分结构定义

    4. 扩展函数


    内容


    1. 源码流程

    1.1 sock_init

    static int __init sock_init(void)
    {
            int err;
            /* 初始化网络sysctl基础结构 */
            err = net_sysctl_init();
            if (err)
                    goto out;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

      net_sysctl_init分析,继续看sock_init:

    /* 初始化skbuff SLAB缓存 */
    skb_init();
    // skbuff_head_cache
    // skbuff_fclone_cache
    // skbuff_ext_cache
    
    /* 初始化protocols模块 */
    init_inodecache();
    // SLAB缓存 -> sock_inode_cache
    
    err = register_filesystem(&sock_fs_type);
    // 注册sockft(socket)文件系统
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

      sockfs_init_fs_context分析,继续看sock_init:

    sock_mnt = kern_mount(&sock_fs_type);
    // 获取文件系统的super_block对象
    // 根目录的inode与dentry对象
    // 加入到链表
    
    #ifdef CONFIG_NETFILTER
            err = netfilter_init();
            if (err)
                    goto out;
    #endif
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

      netfilter_init分析,继续看sock_init:

    ptp_classifier_init(); // 一个独立于任何套接字的过滤器(BPF(Berkeley Packet Filter)伯克利包过滤器,BPF允许用户空间程序将一个过滤(filter)附加到任何的套接字(socket)上面用来允许或不允许某些类型的数据通过socket)
    
    out:
            return err;
            
    out_mount:                                
            unregister_filesystem(&sock_fs_type);
            // 取消注册sockft(socket)文件系统
            goto out;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    1.2 socket文件创建

      socket初始化完成之后,通过文件形式创建相关服务。当执行socket()函数时,内核通过SYSCALL_DEFINE3(socket…) -> __sys_socket进行相关内容加载,进入__sys_socket函数:

    int __sys_socket(int family, int type, int protocol)
    {
            struct socket *sock;
            int flags;
    
            sock = __sys_socket_create(family, type, protocol); // 创建套接字,加入SELINUX策略等等
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

      __sys_socket_create分析,继续看sock_init:

            flags = type & ~SOCK_TYPE_MASK;
            // 清除SOCK_TYPE_MASK标志
            // #define SOCK_TYPE_MASK 0xf
    
            if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
                    flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
    
    
            return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
            // 创建套接字文件,设置文件为流模式,文件指针放入文件描述符表(数组,table[fd])中
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

      sock_map_fd分析


    2. 源码结构

      socket_file_ops

    static const struct file_operations socket_file_ops = {
            .owner =        THIS_MODULE,
            .llseek =       no_llseek,
            .read_iter =    sock_read_iter,
            .write_iter =   sock_write_iter,
            .poll =         sock_poll,
            .unlocked_ioctl = sock_ioctl,
    #ifdef CONFIG_COMPAT
            .compat_ioctl = compat_sock_ioctl,
    #endif
            .mmap =         sock_mmap,
            .release =      sock_close,
            .fasync =       sock_fasync,
            .sendpage =     sock_sendpage,
            .splice_write = generic_splice_sendpage,
            .splice_read =  sock_splice_read,
            .show_fdinfo =  sock_show_fdinfo,
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

      sysctl_table_root

    static struct ctl_table_root sysctl_table_root = {
            .default_set.dir.header = {
                    {{.count = 1,
                      .nreg = 1,
                      .ctl_table = root_table }},
                    .ctl_table_arg = root_table,
                    .root = &sysctl_table_root,
                    .set = &sysctl_table_root.default_set,
            },
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

      sysctl_table_root

    static struct pernet_operations sysctl_pernet_ops = {
            .init = sysctl_net_init,
            .exit = sysctl_net_exit,
    };
    
    • 1
    • 2
    • 3
    • 4

      root_table

    static struct ctl_table root_table[] = {
            {
                    .procname = "",
                    .mode = S_IFDIR|S_IRUGO|S_IXUGO,
            },
            { }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

      sock_fs_type

    static struct file_system_type sock_fs_type = {
            .name =         "sockfs",
            .init_fs_context = sockfs_init_fs_context,
            .kill_sb =      kill_anon_super,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

      xattr_handler

    static const struct xattr_handler *sockfs_xattr_handlers[] = {
            &sockfs_xattr_handler,
            &sockfs_security_xattr_handler,
            NULL
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

      sockfs_ops

    static const struct super_operations sockfs_ops = {
            .alloc_inode    = sock_alloc_inode,
            .free_inode     = sock_free_inode,
            .statfs         = simple_statfs,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

      netfilter_net_ops

    static struct pernet_operations netfilter_net_ops = {
            .init = netfilter_net_init,
            .exit = netfilter_net_exit,
    };
    
    • 1
    • 2
    • 3
    • 4

      sockfs_inode_ops

    static const struct inode_operations sockfs_inode_ops = {
            .listxattr = sockfs_listxattr,
            .setattr = sockfs_setattr,
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3. 部分结构定义

      ctl_table_header,用于维护ctl_table结构树的动态列表

    struct ctl_table_header {
    	union {
    		struct {
    			struct ctl_table *ctl_table;
    			int used;
    			int count;
    			int nreg;
    		};
    		struct rcu_head rcu;
    	};
    	struct completion *unregistering;
    	struct ctl_table *ctl_table_arg;
    	struct ctl_table_root *root;
    	struct ctl_table_set *set;
    	struct ctl_dir *parent;
    	struct ctl_node *node;
    	struct hlist_head inodes; /* head for proc_inode->sysctl_inodes */
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

      ctl_table_header存储结构(红黑树存储结构)

    struct ctl_dir {
    	/* Header must be at the start of ctl_dir */
    	struct ctl_table_header header;
    	struct rb_root root;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

      ctl_table_header存储结构(红黑树存储结构)

    struct ctl_table_set {
    	int (*is_seen)(struct ctl_table_set *);
    	struct ctl_dir dir;
    };
    
    • 1
    • 2
    • 3
    • 4

      socket_alloc

    struct socket_alloc {
    	struct socket socket;
    	struct inode vfs_inode;
    };
    
    • 1
    • 2
    • 3
    • 4

      sock_type

    enum sock_type {
            SOCK_STREAM     = 1,
            SOCK_DGRAM      = 2,
            SOCK_RAW        = 3,
            SOCK_RDM        = 4,
            SOCK_SEQPACKET  = 5,
            SOCK_DCCP       = 6,
            SOCK_PACKET     = 10,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

      支持的地址族

    /* Supported address families. */
    #define AF_UNSPEC       0
    #define AF_UNIX         1       /* Unix domain sockets          */
    #define AF_LOCAL        1       /* POSIX name for AF_UNIX       */
    #define AF_INET         2       /* Internet IP Protocol         */
    #define AF_AX25         3       /* Amateur Radio AX.25          */
    #define AF_IPX          4       /* Novell IPX                   */
    #define AF_APPLETALK    5       /* AppleTalk DDP                */
    #define AF_NETROM       6       /* Amateur Radio NET/ROM        */
    #define AF_BRIDGE       7       /* Multiprotocol bridge         */
    #define AF_ATMPVC       8       /* ATM PVCs                     */
    #define AF_X25          9       /* Reserved for X.25 project    */
    #define AF_INET6        10      /* IP version 6                 */
    #define AF_ROSE         11      /* Amateur Radio X.25 PLP       */
    #define AF_DECnet       12      /* Reserved for DECnet project  */
    #define AF_NETBEUI      13      /* Reserved for 802.2LLC project*/
    #define AF_SECURITY     14      /* Security callback pseudo AF */
    #define AF_KEY          15      /* PF_KEY key management API */
    #define AF_NETLINK      16
    #define AF_ROUTE        AF_NETLINK /* Alias to emulate 4.4BSD */
    #define AF_PACKET       17      /* Packet family                */
    #define AF_ASH          18      /* Ash                          */
    #define AF_ECONET       19      /* Acorn Econet                 */
    #define AF_ATMSVC       20      /* ATM SVCs                     */
    #define AF_RDS          21      /* RDS sockets                  */
    #define AF_SNA          22      /* Linux SNA Project (nutters!) */
    #define AF_IRDA         23      /* IRDA sockets                 */
    #define AF_PPPOX        24      /* PPPoX sockets                */
    #define AF_WANPIPE      25      /* Wanpipe API Sockets */
    #define AF_LLC          26      /* Linux LLC                    */
    #define AF_IB           27      /* Native InfiniBand address    */
    #define AF_MPLS         28      /* MPLS */
    #define AF_CAN          29      /* Controller Area Network      */
    #define AF_TIPC         30      /* TIPC sockets                 */
    #define AF_BLUETOOTH    31      /* Bluetooth sockets            */
    #define AF_IUCV         32      /* IUCV sockets                 */
    #define AF_RXRPC        33      /* RxRPC sockets                */
    #define AF_ISDN         34      /* mISDN sockets                */
    #define AF_PHONET       35      /* Phonet sockets               */
    #define AF_IEEE802154   36      /* IEEE802154 sockets           */
    #define AF_CAIF         37      /* CAIF sockets                 */
    #define AF_ALG          38      /* Algorithm sockets            */
    #define AF_NFC          39      /* NFC sockets                  */
    #define AF_VSOCK        40      /* vSockets                     */
    #define AF_KCM          41      /* Kernel Connection Multiplexor*/
    #define AF_QIPCRTR      42      /* Qualcomm IPC Router          */
    #define AF_SMC          43      /* smc sockets: reserve number for
                                     * PF_SMC protocol family that
                                     * reuses AF_INET address family
                                     */
    #define AF_XDP          44      /* XDP sockets                  */
    #define AF_MCTP         45      /* Management component
                                     * transport protocol
                                     */
    
    #define AF_MAX          46      /* For now.. */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

      支持的SELINE class类型

    #define SECCLASS_SECURITY                                 1
    #define SECCLASS_PROCESS                                  2
    #define SECCLASS_PROCESS2                                 3
    #define SECCLASS_SYSTEM                                   4
    #define SECCLASS_CAPABILITY                               5
    #define SECCLASS_FILESYSTEM                               6
    #define SECCLASS_FILE                                     7
    #define SECCLASS_DIR                                      8
    #define SECCLASS_FD                                       9
    #define SECCLASS_LNK_FILE                                10
    #define SECCLASS_CHR_FILE                                11
    #define SECCLASS_BLK_FILE                                12
    #define SECCLASS_SOCK_FILE                               13
    #define SECCLASS_FIFO_FILE                               14
    #define SECCLASS_SOCKET                                  15
    #define SECCLASS_TCP_SOCKET                              16
    #define SECCLASS_UDP_SOCKET                              17
    #define SECCLASS_RAWIP_SOCKET                            18
    #define SECCLASS_NODE                                    19
    #define SECCLASS_NETLINK_SOCKET                          21
    #define SECCLASS_PACKET_SOCKET                           22
    #define SECCLASS_KEY_SOCKET                              23
    #define SECCLASS_UNIX_STREAM_SOCKET                      24
    #define SECCLASS_UNIX_DGRAM_SOCKET                       25
    #define SECCLASS_SEM                                     26
    #define SECCLASS_MSG                                     27
    #define SECCLASS_MSGQ                                    28
    #define SECCLASS_SHM                                     29
    #define SECCLASS_IPC                                     30
    #define SECCLASS_NETLINK_ROUTE_SOCKET                    31
    #define SECCLASS_NETLINK_TCPDIAG_SOCKET                  32
    #define SECCLASS_NETLINK_NFLOG_SOCKET                    33
    #define SECCLASS_NETLINK_XFRM_SOCKET                     34
    #define SECCLASS_NETLINK_SELINUX_SOCKET                  35
    #define SECCLASS_NETLINK_ISCSI_SOCKET                    36
    #define SECCLASS_NETLINK_AUDIT_SOCKET                    37
    #define SECCLASS_NETLINK_FIB_LOOKUP_SOCKET               38
    #define SECCLASS_NETLINK_CONNECTOR_SOCKET                39
    #define SECCLASS_NETLINK_NETFILTER_SOCKET                40
    #define SECCLASS_NETLINK_DNRT_SOCKET                     41
    #define SECCLASS_ASSOCIATION                             42
    #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET           43
    #define SECCLASS_NETLINK_GENERIC_SOCKET                  44
    #define SECCLASS_NETLINK_SCSITRANSPORT_SOCKET            45
    #define SECCLASS_NETLINK_RDMA_SOCKET                     46
    #define SECCLASS_NETLINK_CRYPTO_SOCKET                   47
    #define SECCLASS_APPLETALK_SOCKET                        48
    #define SECCLASS_PACKET                                  49
    #define SECCLASS_KEY                                     50
    #define SECCLASS_DCCP_SOCKET                             51
    #define SECCLASS_MEMPROTECT                              52
    #define SECCLASS_PEER                                    53
    #define SECCLASS_CAPABILITY2                             54
    #define SECCLASS_KERNEL_SERVICE                          55
    #define SECCLASS_TUN_SOCKET                              56
    #define SECCLASS_BINDER                                  57
    #define SECCLASS_CAP_USERNS                              58
    #define SECCLASS_CAP2_USERNS                             59
    #define SECCLASS_SCTP_SOCKET                             60
    #define SECCLASS_ICMP_SOCKET                             61
    #define SECCLASS_AX25_SOCKET                             62
    #define SECCLASS_IPX_SOCKET                              63
    #define SECCLASS_NETROM_SOCKET                           64
    #define SECCLASS_ATMPVC_SOCKET                           65
    #define SECCLASS_X25_SOCKET                              66
    #define SECCLASS_ROSE_SOCKET                             67
    #define SECCLASS_DECNET_SOCKET                           68
    #define SECCLASS_ATMSVC_SOCKET                           69
    #define SECCLASS_RDS_SOCKET                              70
    #define SECCLASS_IRDA_SOCKET                             71
    #define SECCLASS_PPPOX_SOCKET                            72
    #define SECCLASS_LLC_SOCKET                              73
    #define SECCLASS_CAN_SOCKET                              74
    #define SECCLASS_TIPC_SOCKET                             75
    #define SECCLASS_BLUETOOTH_SOCKET                        76
    #define SECCLASS_IUCV_SOCKET                             77
    #define SECCLASS_RXRPC_SOCKET                            78
    #define SECCLASS_ISDN_SOCKET                             79
    #define SECCLASS_PHONET_SOCKET                           80
    #define SECCLASS_IEEE802154_SOCKET                       81
    #define SECCLASS_CAIF_SOCKET                             82
    #define SECCLASS_ALG_SOCKET                              83
    #define SECCLASS_NFC_SOCKET                              84
    #define SECCLASS_VSOCK_SOCKET                            85
    #define SECCLASS_KCM_SOCKET                              86
    #define SECCLASS_QIPCRTR_SOCKET                          87
    #define SECCLASS_SMC_SOCKET                              88
    #define SECCLASS_INFINIBAND_PKEY                         89
    #define SECCLASS_INFINIBAND_ENDPORT                      90
    #define SECCLASS_BPF                                     91
    #define SECCLASS_XDP_SOCKET                              92
    #define SECCLASS_MCTP_SOCKET                             93
    #define SECCLASS_PERF_EVENT                              94
    #define SECCLASS_ANON_INODE                              95
    #define SECCLASS_IO_URING                                96
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

      支持的SELINE sid类型

    #define SECINITSID_KERNEL                                   1
    #define SECINITSID_SECURITY                                 2
    #define SECINITSID_UNLABELED                                3
    #define SECINITSID_FILE                                     5
    #define SECINITSID_ANY_SOCKET                               8
    #define SECINITSID_PORT                                     9
    #define SECINITSID_NETIF                                   10
    #define SECINITSID_NETMSG                                  11
    #define SECINITSID_NODE                                    12
    #define SECINITSID_DEVNULL                                 27
    
    #define SECINITSID_NUM 27
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

      security_hook_list 安全模块挂钩列表结构,与通用列表宏一起用于常见操作

    struct security_hook_list {
    	struct hlist_node		list;
    	struct hlist_head		*head;
    	union security_list_options	hook;
    	char				*lsm;
    } __randomize_layout;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

      net_proto_family 套接字类型(家族)保存

    struct net_proto_family {
    	int		family;
    	int		(*create)(struct net *net, struct socket *sock,
    				  int protocol, int kern);
    	struct module	*owner;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

      rlimit 对一个进程获取系统资源的数量进行限制

    struct rlimit {
    	__kernel_ulong_t	rlim_cur;
    	__kernel_ulong_t	rlim_max;
    };
    
    • 1
    • 2
    • 3
    • 4

      sock 套接字的网络层表示

    struct sock {
    	/*
    	 * Now struct inet_timewait_sock also uses sock_common, so please just
    	 * don't add nothing before this first member (__sk_common) --acme
    	 */
    	struct sock_common	__sk_common;
    #define sk_node			__sk_common.skc_node
    #define sk_nulls_node		__sk_common.skc_nulls_node
    #define sk_refcnt		__sk_common.skc_refcnt
    #define sk_tx_queue_mapping	__sk_common.skc_tx_queue_mapping
    #ifdef CONFIG_SOCK_RX_QUEUE_MAPPING
    #define sk_rx_queue_mapping	__sk_common.skc_rx_queue_mapping
    #endif
    
    #define sk_dontcopy_begin	__sk_common.skc_dontcopy_begin
    #define sk_dontcopy_end		__sk_common.skc_dontcopy_end
    #define sk_hash			__sk_common.skc_hash
    #define sk_portpair		__sk_common.skc_portpair
    #define sk_num			__sk_common.skc_num
    #define sk_dport		__sk_common.skc_dport
    #define sk_addrpair		__sk_common.skc_addrpair
    #define sk_daddr		__sk_common.skc_daddr
    #define sk_rcv_saddr		__sk_common.skc_rcv_saddr
    #define sk_family		__sk_common.skc_family
    #define sk_state		__sk_common.skc_state
    #define sk_reuse		__sk_common.skc_reuse
    #define sk_reuseport		__sk_common.skc_reuseport
    #define sk_ipv6only		__sk_common.skc_ipv6only
    #define sk_net_refcnt		__sk_common.skc_net_refcnt
    #define sk_bound_dev_if		__sk_common.skc_bound_dev_if
    #define sk_bind_node		__sk_common.skc_bind_node
    #define sk_prot			__sk_common.skc_prot
    #define sk_net			__sk_common.skc_net
    #define sk_v6_daddr		__sk_common.skc_v6_daddr
    #define sk_v6_rcv_saddr	__sk_common.skc_v6_rcv_saddr
    #define sk_cookie		__sk_common.skc_cookie
    #define sk_incoming_cpu		__sk_common.skc_incoming_cpu
    #define sk_flags		__sk_common.skc_flags
    #define sk_rxhash		__sk_common.skc_rxhash
    
    	/* early demux fields */
    	struct dst_entry __rcu	*sk_rx_dst;
    	int			sk_rx_dst_ifindex;
    	u32			sk_rx_dst_cookie;
    
    	socket_lock_t		sk_lock;
    	atomic_t		sk_drops;
    	int			sk_rcvlowat;
    	struct sk_buff_head	sk_error_queue;
    	struct sk_buff_head	sk_receive_queue;
    	/*
    	 * The backlog queue is special, it is always used with
    	 * the per-socket spinlock held and requires low latency
    	 * access. Therefore we special case it's implementation.
    	 * Note : rmem_alloc is in this structure to fill a hole
    	 * on 64bit arches, not because its logically part of
    	 * backlog.
    	 */
    	struct {
    		atomic_t	rmem_alloc;
    		int		len;
    		struct sk_buff	*head;
    		struct sk_buff	*tail;
    	} sk_backlog;
    	struct llist_head defer_list;
    
    #define sk_rmem_alloc sk_backlog.rmem_alloc
    
    	int			sk_forward_alloc;
    	u32			sk_reserved_mem;
    #ifdef CONFIG_NET_RX_BUSY_POLL
    	unsigned int		sk_ll_usec;
    	/* ===== mostly read cache line ===== */
    	unsigned int		sk_napi_id;
    #endif
    	int			sk_rcvbuf;
    
    	struct sk_filter __rcu	*sk_filter;
    	union {
    		struct socket_wq __rcu	*sk_wq;
    		/* private: */
    		struct socket_wq	*sk_wq_raw;
    		/* public: */
    	};
    #ifdef CONFIG_XFRM
    	struct xfrm_policy __rcu *sk_policy[2];
    #endif
    
    	struct dst_entry __rcu	*sk_dst_cache;
    	atomic_t		sk_omem_alloc;
    	int			sk_sndbuf;
    
    	/* ===== cache line for TX ===== */
    	int			sk_wmem_queued;
    	refcount_t		sk_wmem_alloc;
    	unsigned long		sk_tsq_flags;
    	union {
    		struct sk_buff	*sk_send_head;
    		struct rb_root	tcp_rtx_queue;
    	};
    	struct sk_buff_head	sk_write_queue;
    	__s32			sk_peek_off;
    	int			sk_write_pending;
    	__u32			sk_dst_pending_confirm;
    	u32			sk_pacing_status; /* see enum sk_pacing */
    	long			sk_sndtimeo;
    	struct timer_list	sk_timer;
    	__u32			sk_priority;
    	__u32			sk_mark;
    	unsigned long		sk_pacing_rate; /* bytes per second */
    	unsigned long		sk_max_pacing_rate;
    	struct page_frag	sk_frag;
    	netdev_features_t	sk_route_caps;
    	int			sk_gso_type;
    	unsigned int		sk_gso_max_size;
    	gfp_t			sk_allocation;
    	__u32			sk_txhash;
    
    	/*
    	 * Because of non atomicity rules, all
    	 * changes are protected by socket lock.
    	 */
    	u8			sk_gso_disabled : 1,
    				sk_kern_sock : 1,
    				sk_no_check_tx : 1,
    				sk_no_check_rx : 1,
    				sk_userlocks : 4;
    	u8			sk_pacing_shift;
    	u16			sk_type;
    	u16			sk_protocol;
    	u16			sk_gso_max_segs;
    	unsigned long	        sk_lingertime;
    	struct proto		*sk_prot_creator;
    	rwlock_t		sk_callback_lock;
    	int			sk_err,
    				sk_err_soft;
    	u32			sk_ack_backlog;
    	u32			sk_max_ack_backlog;
    	kuid_t			sk_uid;
    	u8			sk_txrehash;
    #ifdef CONFIG_NET_RX_BUSY_POLL
    	u8			sk_prefer_busy_poll;
    	u16			sk_busy_poll_budget;
    #endif
    	spinlock_t		sk_peer_lock;
    	int			sk_bind_phc;
    	struct pid		*sk_peer_pid;
    	const struct cred	*sk_peer_cred;
    
    	long			sk_rcvtimeo;
    	ktime_t			sk_stamp;
    #if BITS_PER_LONG==32
    	seqlock_t		sk_stamp_seq;
    #endif
    	u16			sk_tsflags;
    	u8			sk_shutdown;
    	atomic_t		sk_tskey;
    	atomic_t		sk_zckey;
    
    	u8			sk_clockid;
    	u8			sk_txtime_deadline_mode : 1,
    				sk_txtime_report_errors : 1,
    				sk_txtime_unused : 6;
    
    	struct socket		*sk_socket;
    	void			*sk_user_data;
    #ifdef CONFIG_SECURITY
    	void			*sk_security;
    #endif
    	struct sock_cgroup_data	sk_cgrp_data;
    	struct mem_cgroup	*sk_memcg;
    	void			(*sk_state_change)(struct sock *sk);
    	void			(*sk_data_ready)(struct sock *sk);
    	void			(*sk_write_space)(struct sock *sk);
    	void			(*sk_error_report)(struct sock *sk);
    	int			(*sk_backlog_rcv)(struct sock *sk,
    						  struct sk_buff *skb);
    #ifdef CONFIG_SOCK_VALIDATE_XMIT
    	struct sk_buff*		(*sk_validate_xmit_skb)(struct sock *sk,
    							struct net_device *dev,
    							struct sk_buff *skb);
    #endif
    	void                    (*sk_destruct)(struct sock *sk);
    	struct sock_reuseport __rcu	*sk_reuseport_cb;
    #ifdef CONFIG_BPF_SYSCALL
    	struct bpf_local_storage __rcu	*sk_bpf_storage;
    #endif
    	struct rcu_head		sk_rcu;
    	netns_tracker		ns_tracker;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190

      proto 我们附加到套接字的网络协议块,套接字层 -> 传输层接口

    struct proto {
    	void			(*close)(struct sock *sk,
    					long timeout);
    	int			(*pre_connect)(struct sock *sk,
    					struct sockaddr *uaddr,
    					int addr_len);
    	int			(*connect)(struct sock *sk,
    					struct sockaddr *uaddr,
    					int addr_len);
    	int			(*disconnect)(struct sock *sk, int flags);
    
    	struct sock *		(*accept)(struct sock *sk, int flags, int *err,
    					  bool kern);
    
    	int			(*ioctl)(struct sock *sk, int cmd,
    					 unsigned long arg);
    	int			(*init)(struct sock *sk);
    	void			(*destroy)(struct sock *sk);
    	void			(*shutdown)(struct sock *sk, int how);
    	int			(*setsockopt)(struct sock *sk, int level,
    					int optname, sockptr_t optval,
    					unsigned int optlen);
    	int			(*getsockopt)(struct sock *sk, int level,
    					int optname, char __user *optval,
    					int __user *option);
    	void			(*keepalive)(struct sock *sk, int valbool);
    #ifdef CONFIG_COMPAT
    	int			(*compat_ioctl)(struct sock *sk,
    					unsigned int cmd, unsigned long arg);
    #endif
    	int			(*sendmsg)(struct sock *sk, struct msghdr *msg,
    					   size_t len);
    	int			(*recvmsg)(struct sock *sk, struct msghdr *msg,
    					   size_t len, int noblock, int flags,
    					   int *addr_len);
    	int			(*sendpage)(struct sock *sk, struct page *page,
    					int offset, size_t size, int flags);
    	int			(*bind)(struct sock *sk,
    					struct sockaddr *addr, int addr_len);
    	int			(*bind_add)(struct sock *sk,
    					struct sockaddr *addr, int addr_len);
    
    	int			(*backlog_rcv) (struct sock *sk,
    						struct sk_buff *skb);
    	bool			(*bpf_bypass_getsockopt)(int level,
    							 int optname);
    
    	void		(*release_cb)(struct sock *sk);
    
    	/* Keeping track of sk's, looking them up, and port selection methods. */
    	int			(*hash)(struct sock *sk);
    	void			(*unhash)(struct sock *sk);
    	void			(*rehash)(struct sock *sk);
    	int			(*get_port)(struct sock *sk, unsigned short snum);
    	void			(*put_port)(struct sock *sk);
    #ifdef CONFIG_BPF_SYSCALL
    	int			(*psock_update_sk_prot)(struct sock *sk,
    							struct sk_psock *psock,
    							bool restore);
    #endif
    
    	/* Keeping track of sockets in use */
    #ifdef CONFIG_PROC_FS
    	unsigned int		inuse_idx;
    #endif
    
    #if IS_ENABLED(CONFIG_MPTCP)
    	int			(*forward_alloc_get)(const struct sock *sk);
    #endif
    
    	bool			(*stream_memory_free)(const struct sock *sk, int wake);
    	bool			(*sock_is_readable)(struct sock *sk);
    	/* Memory pressure */
    	void			(*enter_memory_pressure)(struct sock *sk);
    	void			(*leave_memory_pressure)(struct sock *sk);
    	atomic_long_t		*memory_allocated;	/* Current allocated memory. */
    	struct percpu_counter	*sockets_allocated;	/* Current number of sockets. */
    
    	/*
    	 * Pressure flag: try to collapse.
    	 * Technical note: it is used by multiple contexts non atomically.
    	 * All the __sk_mem_schedule() is of this nature: accounting
    	 * is strict, actions are advisory and have some latency.
    	 */
    	unsigned long		*memory_pressure;
    	long			*sysctl_mem;
    
    	int			*sysctl_wmem;
    	int			*sysctl_rmem;
    	u32			sysctl_wmem_offset;
    	u32			sysctl_rmem_offset;
    
    	int			max_header;
    	bool			no_autobind;
    
    	struct kmem_cache	*slab;
    	unsigned int		obj_size;
    	slab_flags_t		slab_flags;
    	unsigned int		useroffset;	/* Usercopy region offset */
    	unsigned int		usersize;	/* Usercopy region size */
    
    	unsigned int __percpu	*orphan_count;
    
    	struct request_sock_ops	*rsk_prot;
    	struct timewait_sock_ops *twsk_prot;
    
    	union {
    		struct inet_hashinfo	*hashinfo;
    		struct udp_table	*udp_table;
    		struct raw_hashinfo	*raw_hash;
    		struct smc_hashinfo	*smc_hash;
    	} h;
    
    	struct module		*owner;
    
    	char			name[32];
    
    	struct list_head	node;
    #ifdef SOCK_REFCNT_DEBUG
    	atomic_t		socks;
    #endif
    	int			(*diag_destroy)(struct sock *sk, int err);
    } __randomize_layout;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123

    4. 扩展函数

    net_sysctl_init

    static struct ctl_table_header *net_header;
    __init int net_sysctl_init(void)
    {
            static struct ctl_table empty[1];
            int ret = -ENOMEM;
            net_header = register_sysctl("net", empty); // 注册"net",插入ctl_dir结构
            
            /* 注册网络名称空间子系统 */
            ret = register_pernet_subsys(&sysctl_pernet_ops)
            // 注册一个子系统,该子系统在创建和销毁网络名称空间时分别调用init和exit函数
            // 当注册所有网络命名空间时,将为每个现有的网络命名空间调用init函数。允许内核模块对网络名称空间集有一个竞免视图
    
            out:
            return ret;
    out1:
            unregister_sysctl_table(net_header);// 取消注册sysctl表层次结构
            // 注销sysctl表和所有子表
            // Proc条目可能不会被实际删除,直到它们不再被任何人使用
            net_header = NULL;
            goto out;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    sockfs_init_fs_context

    static int sockfs_init_fs_context(struct fs_context *fc)
    {
            /* 伪文件系统的常见助手(sockfs、pipefs、bdev-永远无法装载的东西)*/
            struct pseudo_fs_context *ctx = init_pseudo(fc, SOCKFS_MAGIC);
            // 初始化伪文件系统上下文
            // #define SOCKFS_MAGIC            0x534F434B
    
            
            ctx->ops = &sockfs_ops; // sockfs操作
            // sock_alloc_inode 为指定的超级块分配一个分配socket_alloc对象
            // simple_statfs 获取sockfs文件系统的状态信息
    
            ctx->dops = &sockfs_dentry_operations; // 动态名称操作(socket:[%lu])
            ctx->xattr = sockfs_xattr_handlers; // sockfs文件系统扩展属性操作
            return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    netfilter_init

    int __init netfilter_init(void)
    {
            int ret;
    
            /* 注册网络过滤器子系统 */
            ret = register_pernet_subsys(&netfilter_net_ops);
    
            /* 注册网络过滤器日志子系统 */
            ret = netfilter_log_init();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    __sys_socket_create

    static struct socket *__sys_socket_create(int family, int type, int protocol)
    {
            struct socket *sock;
            int retval;
    
            /* Check the SOCK_* constants for consistency.  */
            BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
            // #define SOCK_CLOEXEC    O_CLOEXEC
            // O_CLOEXEC       02000000
    
            BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
            // #define SOCK_MAX (SOCK_PACKET + 1)
            // #define SOCK_TYPE_MASK 0xf
    
            BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
            BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
            // #define O_NONBLOCK      00004000
    
            if ((type & ~SOCK_TYPE_MASK) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
                    return ERR_PTR(-EINVAL);
            type &= SOCK_TYPE_MASK;
    
            /* 创建一个套接字 */
            retval = sock_create(family, type, protocol, &sock);
            ||
            \/
            int sock_create(int family, int type, int protocol, struct socket **res)
            {
                    return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
            }
            ||
            \/
            int __sock_create(struct net *net, int family, int type, int protocol,
                             struct socket **res, int kern)
            {
                    int err;
                    struct socket *sock;
                    const struct net_proto_family *pf;
    
                    if (family < 0 || family >= NPROTO)
                    // #define NPROTO          AF_MAX
                            return -EAFNOSUPPORT;
    
                    if (type < 0 || type >= SOCK_MAX)
                            return -EINVAL;
    
                    if (family == PF_INET && type == SOCK_PACKET) {
                    // PF_INET 从INET层移到这里,以避免模块加载中的死锁
                    // PF_INET 互联网IP协议
                            pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
                                    current->comm);
                            family = PF_PACKET;
                            // PF_PACKET 数据包家族
                    }
    
                    err = security_socket_create(family, type, protocol, kern);
                    // 针对套接字家族类型检查,创建socksid(源安全标识符),加入SELINUX策略等等
                    // socket_create函数是由安全模块定义的钩子,它是管理系统安全策略的众多 LSM(Linux 安全模块)挂钩之一。LSM 实际上是一个允许内核支持多种安全模型的框架。通常会有一个安全模块将自己注册到内核的 LSM 框架中
                    // LSM_HOOK(int, 0, socket_create, int family, int type, int protocol, int kern) 
                    // socket_create -> 执行selinux_socket_create
    
                    /* 分配一个新的inode和socket对象
                     两者绑定在一起并初始化
                     然后返回套接字 */
                    sock = sock_alloc();
    
                    sock->type = type;
                    // 套接字数据流类型 %SOCK_STREAM
    
    #ifdef CONFIG_MODULES
                    /* 如果查找失败,则尝试加载协议模块 */
                    if (rcu_access_pointer(net_families[family]) == NULL)
                            request_module("net-pf-%d", family);
    #endif
                    ...
                    pf = rcu_dereference(net_families[family]);// 获取套接字(类型)家族指针以解除引用
    
                    if (!try_module_get(pf->owner)) // 检查module->refcnt,它位于可加载模块中
                            goto out_release;
    
                    err = pf->create(net, sock, protocol, kern);
                    // net_proto_family对象由sock_register创建,在ipv4中分析
    
                    /* 为了在sock_release时拥有这个套接字的 
                    [xxxx]模块的refcnt,我们减少它的 refcnt */
                    if (!try_module_get(sock->ops->owner))
                    goto out_module_busy;     
    
                    /* 现在我们已经完成了 ->create 函数,[xxxx]模块可以减少module->refcnt */
                    module_put(pf->owner);
                    err = security_socket_post_create(sock, family, type, protocol, kern);
                    // 针对套接字家族类型检查,创建socksid(源安全标识符),创建SELINUX class,加入SELINUX策略等等
                    // 尝试使用给定SID使用NetLabel机制标记套接字
                    // socket_post_create -> selinux_socket_post_create
                    if (err)
                            goto out_sock_release;
                    *res = sock;
                    
                    return 0;
    
            out_module_busy:
                    err = -EAFNOSUPPORT;
            out_module_put:
                    sock->ops = NULL;
                    module_put(pf->owner);
            out_sock_release:
                    sock_release(sock);
                    return err;
    
            out_release:
                    rcu_read_unlock();
                    goto out_sock_release;
            }
            ...
            if (retval < 0)
                    return ERR_PTR(retval);
    
            return sock;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119

    sock_map_fd

    static int sock_map_fd(struct socket *sock, int flags)
    {
            struct file *newfile;
            int fd = get_unused_fd_flags(flags);
            // 分配文件描述符,flags写入相关结构体内,如果设置O_CLOEXEC标志,表示文件未打开
            // # define RLIMIT_NOFILE          7       /* max number of open files */
    
            if (unlikely(fd < 0)) {
                    sock_release(sock);
                    return fd;
            }
    
            newfile = sock_alloc_file(sock, flags, NULL);
            ||
            \/
            struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
            {               
            struct file *file;
    
            if (!dname)
                    dname = sock->sk ? sock->sk->sk_prot_creator->name : "";
                    // 传输层(proto)名称
            
            file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname,
                                    O_RDWR | (flags & O_NONBLOCK),
                                    &socket_file_ops);
            // 生成套接字文件,赋值文件权限,文件包括read_iter,write_iter,unlocked_ioctl等函数接口
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

      alloc_file_pseudo分析,继续看sock_alloc_file:

            sock->file = file; // 套接字赋值文件
            file->private_data = sock; // 设置文件私有数据段
            stream_open(SOCK_INODE(sock), file); // 去掉文件中的读写等标志,增加FMODE_STREAM标志
            return file;
    }
    ...
    回到sock_map_fd函数:
            if (!IS_ERR(newfile)) {
                    fd_install(fd, newfile); // 文件指针放入文件描述符表(数组)中
                    return fd;
            }
    
            put_unused_fd(fd);
            return PTR_ERR(newfile);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    alloc_file_pseudo

    struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,
                                    const char *name, int flags,
                                    const struct file_operations *fops)
    {
            static const struct dentry_operations anon_ops = {
                    .d_dname = simple_dname
            };
            struct qstr this = QSTR_INIT(name, strlen(name));
            struct path path;
            struct file *file;
    
            path.dentry = d_alloc_pseudo(mnt->mnt_sb, &this);
            // 分配一个伪文件系统,文件目录存在于内存中,并且在删除最后一个引用和释放它们之间不会有RCU延迟
    
            if (!mnt->mnt_sb->s_d_op)
                    d_set_d_op(path.dentry, &anon_ops); // 设置目录名称及标志检查/赋值
            
            path.mnt = mntget(mnt); // 获取vfsmount对象, vfsmount引用计数加1
            d_instantiate(path.dentry, inode); // path.dentry记录inode及inode标志
    
            file = alloc_file(&path, flags, fops);
            // 分配套接字文件,设置文件权限(模式),文件路径,文件inode,读计数增加等等
            // fops是file_operations结构对象socket_file_ops
            // 包含read_iter,write_iter,unlocked_ioctl等函数接口
    
            if (IS_ERR(file)) {
                    ihold(inode);
                    path_put(&path);
            }
            return file;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    一些杂题(9.23)
    罗克韦尔AB PLC RSLogix5000中计数器指令使用方法介绍
    临床信息去冗余 临床数据处理分组不同的GSE数据集有不同的临床信息,不同的分组技巧
    Linux常用命令——builtin命令
    工程制造领域:企业IT架构
    重学数据库进阶
    揭秘你代理商做不起来货卖不出去的原因,探讨其背后的商业逻辑
    3D激光线轮廓传感器市场需求,预计2029年将达到734.86百万美元。
    ElementPlus· tab切换/标签切换 + 分页
    接口访问量统计
  • 原文地址:https://blog.csdn.net/a29562268/article/details/126075545