ãLinuxã«ã¼ãã«2.6解èªå®¤ãï¼ä»¥éãæ§çï¼åºçå¾ãLinuxã«ã¯å¤ãã®æ©è½ã追å ãããã¨ã³ã¿ã¼ãã©ã¤ãºé åãã¯ããã¨ããæ§ã ãªå ´æã§ä½¿ãããããã«ãªãã¾ããã ããã«ä¼´ãã³ã¼ããè¥å¤§ãã¤è¤éåããå¤ãã®ã¨ã³ã¸ãã¢ã«ã¨ã£ã¦è§£èªä¸è½ãªãã©ãã¯ããã¯ã¹ã¨ãªã£ã¦ãã¾ãã ä¸çä¸ã®ãããã¨ã³ã¸ãã¢éã®åä½ã§ããLinuxã«ã¼ãã«ã«ã¡ã¹ãå ¥ãããã©ãã¯ããã¯ã¹ãããéãã¦ãæã«å¥½å¥å¿ã®èµ´ãã¾ã¾ã«ã«ã¼ãã«ã®ä¸çã解èªãããæ°Linuxã«ã¼ãã«è§£èªå®¤ãããã¸ã§ã¯ãã
æ¬ç¨¿ã§ã¯ãæ§ç第21ç« ã§è§£èª¬ããã¦ããã½ã±ããã¤ã³ã¿ã¼ãã§ã¼ã¹ã«ã¤ãã¦ãã«ã¼ãã«v6.8ã®ã³ã¼ãããã¼ã¹ã«ä¸»ã«ãã¼ã¿æ§é ãä¸å¿ã«è§£èª¬ãã¾ãã
å·çè : é ç° å²å¿ã稲è è²´æ
â» ãæ°Linuxã«ã¼ãã«è§£èªå®¤ãé£è¼è¨äºä¸è¦§ã¯ãã¡ã
ã¯ããã«
ã¢ããªã±ã¼ã·ã§ã³ããããã¯ã¼ã¯ãå©ç¨ããå ´åãsocket(2)
ã·ã¹ãã ã³ã¼ã«ã§ã½ã±ãããä½æããconnect(2)
/bind(2)
/listen(2)
/accept(2)
ã¨ãã£ãå°ç¨ã®ã·ã¹ãã ã³ã¼ã«ã使ããã¨ã§ä»ã®ã¢ããªã±ã¼ã·ã§ã³ã¨éä¿¡ãããã¨ãã§ãã¾ãã
ã¨ããã§socket(2)
ã«ãã£ã¦ä½æãããã½ã±ããã¯ã¢ããªã±ã¼ã·ã§ã³ããè¦ãã¨ãã½ã±ãããã£ã¹ã¯ãªãã¿ã¨ãã¦åå¾ããã¾ãã
ã¾ãããã¡ã¤ã«æä½ã®ããã®read(2)
/write(2)
ã¨ãã£ãã·ã¹ãã ã³ã¼ã«ãããã®ã½ã±ãããã£ã¹ã¯ãªãã¿ã«å¯¾ãã¦ä½¿ç¨ãããã¨ãã§ãã¾ãã
ããªãã¡ã½ã±ãããã£ã¹ã¯ãªãã¿ã¯ãã¡ã¤ã«ã®å´é¢ãæã£ã¦ããã¨ãããã¨ã§ãã
ããã§ã¯ã½ã±ããã¨ã¯ä¸ä½ä½ãªã®ã§ããããã
ã½ã±ããã®å®ä½ã¨ãªããã¼ã¿æ§é ã¯socketæ§é ä½ã¨sockæ§é ä½ã«ãªãã¾ãã
ããã¦ãããã¯sockfsã¨ããçä¼¼ãã¡ã¤ã«ã·ã¹ãã ã¨ãã¦æ½è±¡å/å®è£
ããã¦ãããããã«ãããã¡ã¤ã«ã¨ãã¦ã®æä½ãå®ç¾ãã¦ãã¾ãã
æ¬ç¨¿ã§ã¯ãããã³ã«ãã¨ã«ç°ãªãå¦çãã½ã±ãããã©ã®ããã«æ½è±¡åãã¦ããã®ããã¾ãã½ã±ããããªããã¡ã¤ã«ã¨ãã¦æä½ã§ããã®ãã«ã¤ãã¦ããã¼ã¿æ§é ãä¸å¿ã«è¦ã¦ããããã¨æãã¾ãã
ã½ã±ããã®å®ä½ã¨æ¦è¦
åè¿°ã®ã¨ããã½ã±ããã®å®ä½ã¨ãªããã¼ã¿æ§é ã¯socketæ§é ä½ã¨sockæ§é ä½ã«ãªãã¾ãã
ããã¦ããããã¯ãã¡ã¤ã«æä½ã®ããã®ã·ã¹ãã ã³ã¼ã«ããå©ç¨ã§ãããããä½ããã®å½¢ã§fileæ§é ä½çã¨é¢é£ä»ãããã¦ãã¾ãã
å®éã«socketæ§é ä½ãsockæ§é ä½ã®ã½ã¼ã¹ã³ã¼ããè¦ãã¨ä»¥ä¸ã®ããã«äºãã«ãã¤ã³ã¿ã§é¢é£ä»ãããã¦ãããã¨ããããã¾ãã*1
ã½ã±ããã¯socketæ§é ä½ã¨sockæ§é ä½ã®2ã¤ã«åé¢ããã¦ãã¾ãããsocketæ§é ä½ã¯BSDç±æ¥ã®socket APIã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ãã®ãã®ã表ç¾ãã¦ãããsockæ§é ä½ã¯ãããã¯ã¼ã¯ã¬ã¤ã¤ã¼ã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ã表ãã¦ãã¾ãã ãã®ãããIPv4/IPv6ãªã©ãããã³ã«ã«ãã£ã¦sockæ§é ä½ã®åæåå¦çãç»é²ããã³ã¼ã«ããã¯é¢æ°ã¯ç°ãªã£ã¦ãã¾ãã ã¾ããsocketæ§é ä½ãfileæ§é ä½ã¸ã®ãã¤ã³ã¿ãæã£ã¦ãããã¨ãããsocket APIããã¡ã¤ã«ã¨é¢é£ã¥ãããã¦ãããã¨ããããã¨æãã¾ãã
ã½ã±ããæä½é¢æ°ã®å®è£
éä¿¡ã®ãã³ããªã³ã°ã®ä»æ¹ã¯ãããã³ã«ãã¨ã«ç°ãªãã¾ãããã½ã±ããã使ããã¨ã§ã¢ããªã±ã¼ã·ã§ã³ã¯ããããã»ã¨ãã©æèããã«éä¿¡ãè¡ããã¨ãã§ãã¾ããããã¯ãããã³ã«ãã¨ã®å·®ç°ãã³ã¼ã«ããã¯é¢æ°ã«ãã£ã¦æ½è±¡åãããã¨ã§å®ç¾ããã¦ãã¾ããå
·ä½ä¾ã¨ãã¦ã½ã±ããæä½é¢æ°(ã·ã¹ãã ã³ã¼ã«)ã§ããsendmsg(2)
/recvmsg(2)
ãä¾ã«ã½ã±ãããã©ã®ããã«ãããã³ã«ãã¨ã®å·®ç°ãæ½è±¡åãã¦ããã®ãè¦ã¦ã¿ã¾ãããã
ã¾ãsendmsg(2)
ã®ã½ã¼ã¹ã³ã¼ãã辿ã£ã¦ããã¨ä»¥ä¸ã®ããã«é¢æ°ãå¼ã³åºããã¦ãããã¨ããããã¾ãã(主è¦ãªé¢æ°ããåãä¸ãã¦ãã¾ãã)
sendmsg() âââ __sys_sendmsg() âââ sockfd_lookup_light() âââ ___sys_sendmsg() âââ ____sys_sendmsg() âââ sock_sendmsg_nosec() âââ sock->ops->sendmsg
åæ§ã«ãã¦recvmsg(2)
ã®ã½ã¼ã¹ã³ã¼ãã辿ã£ã¦ã¿ãã¨ä»¥ä¸ã®ããã«é¢æ°ãå¼ã³åºããã¦ãããã¨ããããã¾ãã
recvmsg() âââ __sys_recvmsg() âââ sockfd_lookup_light() âââ ___sys_recvmsg() âââ ____sys_recvmsg() âââ sock_recvmsg() âââ sock_recvmsg_nosec() âââ sock->ops->recvmsg
ã©ã¡ãã®ã·ã¹ãã ã³ã¼ã«ãé常ã«ä¼¼ãé¢æ°ã®å¼ã³åºãæ§é ã«ãªã£ã¦ãã¾ããæåã«sockfd_lookup_light()
ã§ã½ã±ãããã£ã¹ã¯ãªãã¿(ãã¡ã¤ã«ãã£ã¹ã¯ãªãã¿)ã«å¯¾å¿ããsocketæ§é ä½ãåå¾ããæçµçã«sock->ops
å
ã®ã³ã¼ã«ããã¯é¢æ°ãå¼ãã§ãã¾ãã
ãã®sock->ops
ã¯ãsocketæ§é ä½ãåç
§ãã¦ããproto_opsæ§é ä½ã§ãã以ä¸ã®ãããªæ§é ã«ãªã£ã¦ãã¾ãã
â»å¤æ°åãsock
ã¨ãªã£ã¦ãã¾ãããsockæ§é ä½ã§ã¯ãªãsocketæ§é ä½ãæãã¦ãã¾ããé常ã«ç´ããããã§ããã
struct proto_ops { int family; struct module *owner; int (*release) (struct socket *sock); int (*bind) (struct socket *sock, struct sockaddr *myaddr, int sockaddr_len); int (*connect) (struct socket *sock, struct sockaddr *vaddr, int sockaddr_len, int flags); int (*socketpair)(struct socket *sock1, struct socket *sock2); int (*accept) (struct socket *sock, struct socket *newsock, int flags, bool kern); int (*getname) (struct socket *sock, struct sockaddr *addr, int peer); __poll_t (*poll) (struct file *file, struct socket *sock, struct poll_table_struct *wait); int (*ioctl) (struct socket *sock, unsigned int cmd, unsigned long arg); #ifdef CONFIG_COMPAT int (*compat_ioctl) (struct socket *sock, unsigned int cmd, unsigned long arg); #endif int (*gettstamp) (struct socket *sock, void __user *userstamp, bool timeval, bool time32); int (*listen) (struct socket *sock, int len); int (*shutdown) (struct socket *sock, int flags); int (*setsockopt)(struct socket *sock, int level, int optname, sockptr_t optval, unsigned int optlen); int (*getsockopt)(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen); void (*show_fdinfo)(struct seq_file *m, struct socket *sock); int (*sendmsg) (struct socket *sock, struct msghdr *m, size_t total_len); /* Notes for implementing recvmsg: * =============================== * msg->msg_namelen should get updated by the recvmsg handlers * iff msg_name != NULL. It is by default 0 to prevent * returning uninitialized memory to user space. The recvfrom * handlers can assume that msg.msg_name is either NULL or has * a minimum size of sizeof(struct sockaddr_storage). */ int (*recvmsg) (struct socket *sock, struct msghdr *m, size_t total_len, int flags); int (*mmap) (struct file *file, struct socket *sock, struct vm_area_struct * vma); ssize_t (*splice_read)(struct socket *sock, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags); void (*splice_eof)(struct socket *sock); int (*set_peek_off)(struct sock *sk, int val); int (*peek_len)(struct socket *sock); /* The following functions are called internally by kernel with * sock lock already held. */ int (*read_sock)(struct sock *sk, read_descriptor_t *desc, sk_read_actor_t recv_actor); /* This is different from read_sock(), it reads an entire skb at a time. */ int (*read_skb)(struct sock *sk, skb_read_actor_t recv_actor); int (*sendmsg_locked)(struct sock *sk, struct msghdr *msg, size_t size); int (*set_rcvlowat)(struct sock *sk, int val); };
ã¡ã³ãå¤æ°ã®ã»ã¨ãã©ãã³ã¼ã«ããã¯é¢æ°ã«ãªã£ã¦ãããã¾ãã½ã±ããæä½ã®ããã®ã·ã¹ãã ã³ã¼ã«åã¨é¢é£ãã¦ããããªãã®ãå¤ããã¨ããããã¾ãã ããã¾ã§ãä¸åº¦å³ã«è¡¨ãã¨ä»¥ä¸ã®ãããªæ§æã«ãªã£ã¦ãããã¨ããããã¾ãã*2 ã½ã±ããæä½ç¨ã®ã·ã¹ãã ã³ã¼ã«ãçºè¡ããã¨å¤ãã¯ããã®proto_opsæ§é ä½å ã®ã³ã¼ã«ããã¯é¢æ°ã«å¦çã移ãã¾ãã Linuxã«ã¼ãã«ã§ã¯ã½ã±ããçææã«socketæ§é ä½ãåç §ããporot_opsæ§é ä½ããããã³ã«ã«åããã¦ç»é²ãããã¨ã§ãããã³ã«ãã¨ã®å¦çã®å·®ãå¸åãã¦ãã¾ãã
ããã«ããã§proto_opsæ§é ä½ã®ã³ã¼ã«ããã¯é¢æ°ãå°ã追ã£ã¦ã¿ã¾ãããã
socketæ§é ä½ãåç
§ããproto_opsæ§é ä½ã¯ãããã³ã«ã«ãã£ã¦ç°ãªããããããã§ã¯ä¸ä¾ã¨ãã¦proto_opsæ§é ä½ã«inet_stream_opsãæå®ãããå ´åãä¾ã«è¿½ã£ã¦ã¿ã¾ãã
inet_stream_opsã¯socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
ã§ã½ã±ãããçæãããå ´åã«ç»é²ããã¾ãã
const struct proto_ops inet_stream_ops = { .family = PF_INET, .owner = THIS_MODULE, .release = inet_release, .bind = inet_bind, .connect = inet_stream_connect, .socketpair = sock_no_socketpair, .accept = inet_accept, .getname = inet_getname, .poll = tcp_poll, .ioctl = inet_ioctl, .gettstamp = sock_gettstamp, .listen = inet_listen, .shutdown = inet_shutdown, .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, .sendmsg = inet_sendmsg, .recvmsg = inet_recvmsg, #ifdef CONFIG_MMU .mmap = tcp_mmap, #endif .splice_eof = inet_splice_eof, .splice_read = tcp_splice_read, .read_sock = tcp_read_sock, .read_skb = tcp_read_skb, .sendmsg_locked = tcp_sendmsg_locked, .peek_len = tcp_peek_len, #ifdef CONFIG_COMPAT .compat_ioctl = inet_compat_ioctl, #endif .set_rcvlowat = tcp_set_rcvlowat, }; EXPORT_SYMBOL(inet_stream_ops);
å
ã»ã©ã®ä¾ã«åããã¦ã.sendmsg
ã¨.recvmsg
ã«ç»é²ããã¦ããé¢æ°inet_sendmsg
ã¨inet_recvmsg
ãè¦ã¦ã¿ã¾ãããã
int inet_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) { struct sock *sk = sock->sk; if (unlikely(inet_send_prepare(sk))) return -EAGAIN; return INDIRECT_CALL_2(sk->sk_prot->sendmsg, tcp_sendmsg, udp_sendmsg, sk, msg, size); } EXPORT_SYMBOL(inet_sendmsg); ... int inet_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags) { struct sock *sk = sock->sk; int addr_len = 0; int err; if (likely(!(flags & MSG_ERRQUEUE))) sock_rps_record_flow(sk); err = INDIRECT_CALL_2(sk->sk_prot->recvmsg, tcp_recvmsg, udp_recvmsg, sk, msg, size, flags, &addr_len); if (err >= 0) msg->msg_namelen = addr_len; return err; } EXPORT_SYMBOL(inet_recvmsg);
ã©ã¡ãã®é¢æ°ãæçµçã«sk->sk_prot
å
ã®ã³ã¼ã«ããã¯é¢æ°ãå¼ã³åºãã¦ãããå¦çã®å®ä½ã¯ãããã®ã³ã¼ã«ããã¯é¢æ°ã§ãããã¨ããããã¾ãã
(ã©ã¡ããINDIRECT_CALL_2
ãã¯ãã§å
ã¾ãã¦ãã¾ãããçµå±ã¯ç¬¬ä¸å¼æ°ã«ç»é²ããã¦ããsk->sk_prot
å
ã®ã³ã¼ã«ããã¯é¢æ°ãå¼ã°ãããã¨ã¨å義ã§ãã)
sk->sk_prot
ã¯sockæ§é ä½ã®å
é¨(sock_commonæ§é ä½å
)ã§åç
§ãã¦ããprotoæ§é ä½ã§ããã以ä¸ã®é¢ä¿ã«ããã¾ãã
socketæ§é ä½ã§ãããã³ã«ãã¨ã®å·®ç°ãå¸åããããã«å種å¦çãproto_opsæ§é ä½ã§ã³ã¼ã«ããã¯é¢æ°ã¨ãã¦æ½è±¡åãã¦ããã®ã¨åæ§ã«ãsockæ§é ä½ã§ããããã³ã«ãã¨ã®å·®ç°ãå¸åããããã«å¦çãç¶æ
ãprotoæ§é ä½ã使ã£ã¦æ½è±¡åãã¦ãã¾ãã
ä»åã®ä¾ã®ããã«proto_opsæ§é ä½ã®å¦çã®å®ä½ãsockæ§é ä½ã®protoæ§é ä½å´ã«ãããã¨ã¯ãsocketæ§é ä½ãã½ã±ããã¤ã³ã¿ã¼ãã§ã¼ã¹ãã®ãã®ã表ç¾ããsockæ§é ä½ã¯ãããã¯ã¼ã¯ã¬ã¤ã¤ã¼ã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ã表ç¾ãã¦ãããã¨ããããããããã³ã«ã«ä¾åããå¦çãsockæ§é ä½å´ã§å®è£
ãã¦ããã¨èãããã¾ãã
â»ãã ããå
¨ã¦ã®ãããã³ã«ã®å®è£
ãä»åã¨åãå®è£
ã®æ§é ã«ãªã£ã¦ããããã§ã¯ããã¾ããã
ãã¡ã¤ã«æä½é¢æ°ã«ããã½ã±ããæä½ã®å®è£
socket(2)
ã·ã¹ãã ã³ã¼ã«ã«ãã£ã¦åå¾ãããã½ã±ãããã£ã¹ã¯ãªãã¿ã¯ãã¡ã¤ã«æä½ã®ããã®ã·ã¹ãã ã³ã¼ã«ã使ã£ã¦æä½ãããã¨ãã§ãã¾ãã
ããã§ã¯ãã¡ã¤ã«æä½ç¨ã®ã·ã¹ãã ã³ã¼ã«ã§ããread(2)
/write(2)
ãä¾ã«ã½ã±ãããã©ã®ããã«ãã¡ã¤ã«ã¨ãã¦æ½è±¡åããã¦ããã®ãè¦ã¦ããããã¨æãã¾ãã
ã¾ãã¯å
ã¨åæ§ã«read(2)
/write(2)
ã®ããããã®ã½ã¼ã¹ã³ã¼ãã辿ã£ã¦ã¿ã¾ãããã
read(2)
ã®ã½ã¼ã¹ã³ã¼ãã辿ã£ã¦ããã¨ä»¥ä¸ã®ããã«é¢æ°ãå¼ã³åºããã¦ãããã¨ããããã¾ãã(主è¦ãªé¢æ°ããåãä¸ãã¦ãã¾ãã)
read() âââ ksys_read() âââ fdget_pos() âââ vfs_read() âââ new_sync_read() âââ call_read_iter() âââ file->f_op->read_iter
åæ§ã«ãã¦write(2)
ã®ã½ã¼ã¹ã³ã¼ãã辿ã£ã¦ã¿ãã¨ä»¥ä¸ã®ããã«é¢æ°ãå¼ã³åºããã¦ãããã¨ããããã¾ãã
write() âââ ksys_write() âââ fdget_pos() âââ vfs_write() âââ new_sync_write() âââ call_write_iter() âââ file->f_op->write_iter
ã©ã¡ãã®ã·ã¹ãã ã³ã¼ã«ãé常ã«ä¼¼ãé¢æ°ã®å¼ã³åºãæ§é ã«ãªã£ã¦ãããã¨ããããã¾ãã
æåã«fdget_pos()
ã§ãã¡ã¤ã«ãã£ã¹ã¯ãªãã¿ã«å¯¾å¿ããfileæ§é ä½ãåå¾ããæçµçã«file->f_op
å
ã®ã³ã¼ã«ããã¯é¢æ°ãå®è¡ãã¦ãã¾ãã
ããªãã¡ãfile->f_op
å
ã®ã³ã¼ã«ããã¯é¢æ°ãå¦çã®å®ä½ã¨ãããã¨ã«ãªãã¾ãã
f_op
ã¯fileæ§é ä½ãåç
§ãã¦ããfile_operationsæ§é ä½ã§ä»¥ä¸ã®æ§é ãã¨ãã¾ãã
struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); int (*iopoll)(struct kiocb *kiocb, struct io_comp_batch *, unsigned int flags); int (*iterate_shared) (struct file *, struct dir_context *); __poll_t (*poll) (struct file *, struct poll_table_struct *); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); unsigned long mmap_supported_flags; int (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, loff_t, loff_t, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); void (*splice_eof)(struct file *file); int (*setlease)(struct file *, int, struct file_lock **, void **); long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len); void (*show_fdinfo)(struct seq_file *m, struct file *f); #ifndef CONFIG_MMU unsigned (*mmap_capabilities)(struct file *); #endif ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, loff_t, size_t, unsigned int); loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, loff_t len, unsigned int remap_flags); int (*fadvise)(struct file *, loff_t, loff_t, int); int (*uring_cmd)(struct io_uring_cmd *ioucmd, unsigned int issue_flags); int (*uring_cmd_iopoll)(struct io_uring_cmd *, struct io_comp_batch *, unsigned int poll_flags); } __randomize_layout;
æ§é ä½ã®å称ããããããéãããã¡ã¤ã«æä½ã®å¦çã¯ãã®file_operationsæ§é ä½ã«éç´/æ½è±¡åããã¦ãã¾ãã
ããªãã¡ã(socketæ§é ä½ã«ç´ã¥ã)fileæ§é ä½ãåç
§ããfile_operationsæ§é ä½(=f_op
)ã«ã½ã±ããæä½ã®ããã®å¦çãç»é²ãããã¨ã§ãã½ã±ãããã£ã¹ã¯ãªãã¿ããã¡ã¤ã«æä½ç¨ã®ã·ã¹ãã ã³ã¼ã«ã§æ±ããããã«ãªãã¾ãã
ããã¾ã§ã®é¢ä¿ãä¸åº¦æ´çããã¨ä»¥ä¸ã®ããã«ãªãã¾ãã
ããã§ã¯å®éã«file_operationsæ§é ä½ã®ã³ã¼ã«ããã¯é¢æ°ã«ã¯ã©ã®ãããªé¢æ°ãç»é²ããã¦ãããã¿ã¦ã¿ã¾ãããã
詳細ã¯å²æãã¾ããã½ã±ããã®å ´åãã½ã±ããçææã«fileæ§é ä½ã®f_op
ã«ã¯ä»¥ä¸ã®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 .uring_cmd = io_uring_cmd_sock, .mmap = sock_mmap, .release = sock_close, .fasync = sock_fasync, .splice_write = splice_to_socket, .splice_read = sock_splice_read, .splice_eof = sock_splice_eof, .show_fdinfo = sock_show_fdinfo, };
read(2)
/write(2)
ããå¼ã°ãã¦ããread_iter
/write_iter
ã³ã¼ã«ããã¯é¢æ°ã«ã¯ããããsock_read_iter()
/sock_write_iter()
ãç»é²ããã¦ãããã¨ããããã¾ãã
詳細ã¯å²æãã¾ããsock_read_iter()
/sock_write_iter()
ã®ã½ã¼ã¹ã³ã¼ãã辿ãã¨ãããããæçµçã«proto_opsæ§é ä½ã®recvmsg
/sendmsg
ã³ã¼ã«ããã¯é¢æ°ãå®è¡ãã¦ãããã¨ããããã¾ãã
ãã®ä»çµã¿ã«ãããã½ã±ããã¸ã®èªã¿æ¸ãã¨ãã観ç¹ã§ã¯ã½ã±ããæä½ç¨ã®ã·ã¹ãã ã³ã¼ã«recvmsg(2)
/sendmsg(2)
ã使ã£ãå ´åã§ãããã¡ã¤ã«æä½ç¨ã®ã·ã¹ãã ã³ã¼ã«read(2)
/write(2)
ã使ã£ãå ´åã§ãå
é¨ã§ã¯æçµçã«åãå¦ç(proto_opsæ§é ä½ã®ã³ã¼ã«ããã¯é¢æ°)ãå®è¡ãããããã«ãªã£ã¦ãã¾ãã
ããªãã¡ãsocketæ§é ä½ã¨fileæ§é ä½ãç´ã¥ããfile_operationsæ§é ä½ã®å種ã³ã¼ã«ããã¯é¢æ°ã«é©åãªã½ã±ããæä½å¦çé¢æ°ãç»é²ãããã¨ã§ãã½ã±ããã®ãã¡ã¤ã«æ½è±¡åãå®ç¾ãã¦ãã¾ãã ãã®ããã«Linuxã«ã¼ãã«ã§ã¯fileæ§é ä½ããã³file_operationsæ§é ä½ã«ãããã¡ã¤ã«æä½ãæ½è±¡åããã½ã±ããã«å¯¾ããæä½ã¯proto_opsæ§é ä½ã«éç´/æ½è±¡åãããã¨ã§ãããã³ã«ã®å·®ç°ãå¸åããã¨ããæ§é ã«ãªã£ã¦ããã¨è¨ãã¾ãã
ä»åã¯å ·ä½ä¾ã¨ãã¦ã½ã±ããã¸ã®èªã¿æ¸ãã«é¢ããå¦çãåãä¸ãã¾ããããä»ã®ã½ã±ããæä½ç¨ã·ã¹ãã ã³ã¼ã«ããã¡ã¤ã«æä½ç¨ã·ã¹ãã ã³ã¼ã«ã«ã¤ãã¦ãå³7ã«ç¤ºãããã«å¤ããåæ§ã®å®è£ ã«ãªã£ã¦ãã¾ãã*3
次åäºå: ã½ã±ããçæç·¨
ããã¾ã§ãsocketæ§é ä½ã¨sockæ§é ä½ã«ã¯ãã¼ãºã¢ãããã¦ãé¢é£ãããã¼ã¿æ§é ã¨ã¨ãã«ã½ã±ããæä½å¦çã®æµããè¦ã¦ãã¾ããã
ããããsocketæ§é ä½ãsockæ§é ä½ãã¨ãã¾ããã¼ã¿æ§é ã¯å³8ã®ããã«ãã£ã¨å¤ãåå¨ãã¾ãã
ç¹ã«socketæ§é ä½ã¨sockæ§é ä½ããã½ã±ããã®å®ä½ã§ãããã¨ãã¦è¦ã¦ãã¾ããããå®éã«ã¯ãããã®æ§é ä½ã¯ããæ§é ä½ã®ã¡ã³ãå¤æ°ã¨ãã¦åå¨ãã¦ãã¾ãã
â»å³8ã¯socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
ã«ããçæããããã¼ã¿æ§é ã®ä¾ã§ãããããã³ã«ã«ãã£ã¦ä¸é¨ãã¼ã¿æ§é ã¯å¤åãã¾ãã
次åã¯socket(2)
ã·ã¹ãã ã³ã¼ã«ã«ãã£ã¦ãããã®å種ãã¼ã¿æ§é ãã©ã®ããã«çæãããé¢é£ã¥ãããã¦ããã®ããè¦ã¦ããããã¨æãã¾ãã
*1:ã¯ã©ã¹å³é¢¨ã«å¤æ°å: ååã®è¡¨è¨ã§è¡¨ç¾ãã¦ãã¾ããå¾åã®å³ã§ã¯ã¯ã©ã¹å³ã«ã¯ãªã表ç¾ããã ãã®ã§ã¯ã©ã¹å³é¢¨ã¨ãã¾ããã
*2:struct proto_opsã®ããã«ä»åãããããã®ã¯ä¸ååãã¡ã³ãå¤æ°ãä¸ååãã³ã¼ã«ããã¯é¢æ°ã¨ãªãã¾ãã
*3:å³7ã®setsockopt(2)/getsockopt(2)ãã伸ã³ãçµè·¯ã¯levelã«SOL_SOCKET以å¤ãæå®ãã¦å¼ã³åºããå ´åã«ãªãã¾ããSOL_SOCKETãæå®ããå ´åã¯ãproto_opsæ§é ä½ã®ã³ã¼ã«ããã¯é¢æ°ã¯çµç±ããã«sockæ§é ä½ã®ã¡ã³ãå¤æ°ãç´æ¥å¤æ´ããå¦çã«ãªãã¾ãã