ãã®ã¨ã³ããªã®ç¶ãã§ãã
ãã®ã¨ã³ããªã®å 容
macOS ã®ã«ã¼ãã« ( XNU ) ãã½ã¼ã¹ã§ sysctl net.local.stream.sendspace
ã®å¨è¾ºã®ã³ã¼ããçºããå
容ã§ãã
注
ç§ã¯BSDç³»ã®ã«ã¼ãã«ã«é¦´æã¿ããªãã®ã§ãææ¢ãã§èª¿ã¹ã¤ã¤å å®¹ãæ¸ãè¨ããå 容ã«ãªãã¾ããè©³ç´°ã»æ£ç¢ºãªè¨è¿°ã»èª¬æãèªã¿ããå ´åã¯ãå¥ã®ãµã¤ããæç®ãå½ãã£ã¦ãã ããã
macOS ã®ã«ã¼ãã«ã®ã½ã¼ã¹
macOS ã®ã«ã¼ãã«ã¯ XNU ã¨ãã¦å ¬éããã¦ãã¾ããã©ã¤ã»ã³ã¹ã¯ Apple Public Source License 2.0
XNU is ä½?
XNU kernel is part of the Darwin operating system for use in macOS and iOS operating systems. XNU is an acronym for X is Not Unix. XNU is a hybrid kernel combining the Mach kernel developed at Carnegie Mellon University with components from FreeBSD and a C++ API for writing drivers called IOKit. XNU runs on x86_64 for both single processor and multi-processor configurations.
https://github.com/apple/darwin-xnu ã® README.md ããå¼ç¨
以ä¸ã¯ DeepL ã«ãã翻訳
XNUã«ã¼ãã«ã¯ãmacOSãiOSã®OSã§ä½¿ç¨ãããDarwinãªãã¬ã¼ãã£ã³ã°ã·ã¹ãã ã®ä¸é¨ã§ããXNUã¯ãX is Not Unixã®é æåãã¨ã£ããã®ã§ããXNUã¯ãã«ã¼ãã®ã¼ã¡ãã³å¤§å¦ã§éçºãããMachã«ã¼ãã«ã¨FreeBSDã®ã³ã³ãã¼ãã³ããIOKitã¨ãããã©ã¤ããæ¸ãããã®C++APIãçµã¿åããããã¤ããªããã«ã¼ãã«ã§ãããXNU 㯠x86_64 ã§åä½ããã·ã³ã°ã«ããã»ããµã¨ãã«ãããã»ããµã®ä¸¡æ¹ã®æ§æã§åä½ãã¾ãã
UNIX Domain Socket ã®å®è£ 㯠FreeBSD ã®ã³ã³ãã¼ãã³ãã«ãªã£ã¦ãã¾ãã
ã½ã¼ã¹ã®ãã¦ã³ãã¼ã
tar.gz ã¯ä¸è¨ãããã¦ã³ãã¼ãã§ãã¾ã
ã½ã¼ã¹ã github ã«ãã©ã¼ãã¦ãããªãã¸ããªãããã¾ãã
net.local.stream.sendspace ãå®ç¾©ããã¦ããå ´æãæ¢ã
sendspace
ãããã®é©å½ãªã¯ã¼ãã§ grep (ag) ãããã¾ãã£ã¦èª¿ã¹ã¾ããã
ã©ããã bsd/kern/uipc_usrreq.c ã UNIX Domain Socket ã®å®è£ ãæ±ã£ã¦ãããã ã¨çµãè¾¼ãã¾ãããXNU ã®ã½ã¼ã¹ã®ãã¡ãBSD ç±æ¥ã®å®è£ 㯠bsd ãã£ã¬ã¯ããªä»¥ä¸ã«åã¾ã£ã¦ããã§ããã
/* * Both send and receive buffers are allocated PIPSIZ bytes of buffering * for stream sockets, although the total for sender and receiver is * actually only PIPSIZ. * Datagram sockets really use the sendspace as the maximum datagram size, * and don't really want to reserve the sendspace. Their recvspace should * be large enough for at least one max-size datagram plus address. */ #ifndef PIPSIZ #define PIPSIZ 8192 #endif static u_int32_t unpst_sendspace = PIPSIZ; ð static u_int32_t unpst_recvspace = PIPSIZ; static u_int32_t unpdg_sendspace = 2 * 1024; /* really max datagram size */ static u_int32_t unpdg_recvspace = 4 * 1024; static int unp_rights; /* file descriptors in flight */ static int unp_disposed; /* discarded file descriptors */ SYSCTL_DECL(_net_local_stream); SYSCTL_INT(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW | CTLFLAG_LOCKED, &unpst_sendspace, 0, ""); ð SYSCTL_INT(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW | CTLFLAG_LOCKED, &unpst_recvspace, 0, "");
ã¦ã¼ã¶ç©ºéã§ sysctl net.local.stream.sendspace
ã¨ãã¦æ±ãå¤ã¯ãã«ã¼ãã«ç©ºéã§ã¯ u_int32_t unpst_sendspace
ã«åã¾ã£ã¦ããããã§ããsysctl ã®å¤ã static 夿°ã«ãªã£ã¦ããã®ã¯ Linux ã¨ãããªãæãã§ããã
net.local.stream.sendspace ã®ããã©ã«ãå¤
unpst_sendspace
ã®ããã©ã«ãå¤ã¯ PIPSIZ 8192
ã«ãªã£ã¦ãããå
ã®ã¨ã³ããªã§ getsockopt(2) ã§èªã¿åºããå¤ã¨ä¸è´ãã¦ãã¾ãã
sysctl ã®å®ç¾©ãã¯ã
SYSCTL_DECL, SYSCTL_INT ã®ãã¯ãããsysctl ãå®ç¾©ãã¦ããã§ãããã¨ãããªãã¨ãªã顿¨ãã¤ãã¾ã
SYSCTL_DECL(_net_local_stream)
ã§ååã® é層? namespace? ãåºåã£ã¦ãSYSCTL_INT(_net_local_stream, ... &unpst_sendspace )
ã§ sysctl ã®åãå¤ãæ±ã夿°ã®æå®ã屿§ã®æå®ãè¡ã-
CTLFLAG_RW
- sysctl ã®å¤ã¯ã¦ã¼ã¶ç©ºéããèªã¿æ¸ãå¯è½
-
OID_AUTO
- SNMP ã® OID = Object IDentifier ã®æå®ããããªã«ä»»ãã?
-
CTLFLAG_LOCKED
- ãããããããå¤ãèªã¿æ¸ãããéã«ãããã¯ãåã£ãç¶æ ã§æ±ãæå®ã?
ã¨ããæãã§ãããããè±ç·ããã®ã§ãã¯ãã®è©³ç´°ã¾ã§ã¯è¦ã¾ããã
unpst ã¯ãªãã®ç¥ç§°ã?
軽ã調ã¹ãç¨åº¦ã§ã¯ãããã
uipc_usrreq ã¯ãªãã®ç¥ç§°ã?
- UNIX IPC User Request ã?
軽ã調ã¹ãç¨åº¦ã§ã¯ãããã
net.local.stream.sendspace ( unpst_sendspace ) ãåç §ãããã³ã¼ã
unp_attach()ã¨ãã颿°ã®ä¸ã§ soreserve(so, unpst_sendspace, unpst_recvspace);
ã¨ãã¦åç
§ãã¦ãã¾ãã1ï¸â£ ã®é¨åã§ã
static int unp_attach(struct socket *so) { struct unpcb *unp; int error = 0; if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { switch (so->so_type) { case SOCK_STREAM: error = soreserve(so, unpst_sendspace, unpst_recvspace); 1ï¸â£ break; case SOCK_DGRAM: error = soreserve(so, unpdg_sendspace, unpdg_recvspace); break; default: panic("unp_attach"); } if (error) { return error; } } unp = (struct unpcb *)zalloc(unp_zone); if (unp == NULL) { return ENOBUFS; } bzero(unp, sizeof(*unp)); lck_mtx_init(&unp->unp_mtx, &unp_mtx_grp, &unp_mtx_attr); lck_rw_lock_exclusive(&unp_list_mtx); LIST_INIT(&unp->unp_refs); unp->unp_socket = so; 2ï¸â£ unp->unp_gencnt = ++unp_gencnt; unp_count++; LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead : &unp_shead, unp, unp_link); lck_rw_done(&unp_list_mtx); so->so_pcb = (caddr_t)unp; 3ï¸â£ /* * Mark AF_UNIX socket buffers accordingly so that: * * a. In the SOCK_STREAM case, socket buffer append won't fail due to * the lack of space; this essentially loosens the sbspace() check, * since there is disconnect between sosend() and uipc_send() with * respect to flow control that might result in our dropping the * data in uipc_send(). By setting this, we allow for slightly * more records to be appended to the receiving socket to avoid * losing data (which we can't afford in the SOCK_STREAM case). * Flow control still takes place since we adjust the sender's * hiwat during each send. This doesn't affect the SOCK_DGRAM * case and append would still fail when the queue overflows. * * b. In the presence of control messages containing internalized * file descriptors, the append routines will not free them since * we'd need to undo the work first via unp_dispose(). */ so->so_rcv.sb_flags |= SB_UNIX; so->so_snd.sb_flags |= SB_UNIX; return 0; }
soreserve() ã®è©³ç´°ã¯è¿½ãããã¾ãããã struct sock, struct sockbuf ã« unpst_sendspace ã®å¤ãçªã£è¾¼ãã§ãæ§åã
unp_attach is ?
unp_attach 㯠struct socket (ã½ã±ããã®ã¤ã³ã¿ãã§ã¼ã¹) 㨠protocol ( ãããã³ã« ) ãçµã³ã¤ããå®è£ ã®ããã§ã 2ï¸â£ 3ï¸â£
struct socket ã ã½ã±ããã®tã¤ã³ã¿ãã§ã¼ã¹ã¨ãªã£ã¦æ½è±¡åãæããã¦ããããã³ã«ãåãæ¿ããããè¨è¨ã«ãªã£ã¦ãã¾ãã ( ã¤ã³ã¿ãã§ã¼ã¹ãå¤ããã«è£ã®å®è£ ãå¤ããããæ¹ã¯ GoF ã®ãã¶ã¤ã³ãã¿ã¼ã³ã§ãã㨠Strategy ãã¿ã¼ã³ ã«ç¸å½ããã? )
Linux ã§ã struct socket, struct sock ã§åæ§ã®è¨è¨ããã¦ããã®ã§ã顿¨ãã¦çè§£ã§ãã¾ãã
protocol-switch table
unp_attach() ã¯ä¸ä½ã®é¢æ° uipc_attach()ã§å¼ã³åºããã¦ãããuipc_attach() ã¯ããã« uipc_usrreqs ã¨ããæ§é ä½ã§é¢æ°ãã¼ãã«ã«ãªã£ã¦ããã
struct uipc_usrreqs = {
.pru_abort = uipc_abort,
.pru_accept = uipc_accept,
.pru_attach = uipc_attach,
.pru_bind = uipc_bind,
.pru_connect = uipc_connect,
.pru_connect2 = uipc_connect2,
.pru_detach = uipc_detach,
.pru_disconnect = uipc_disconnect,
.pru_listen = uipc_listen,
.pru_peeraddr = uipc_peeraddr,
.pru_rcvd = uipc_rcvd,
.pru_send = uipc_send,
.pru_sense = uipc_sense,
.pru_shutdown = uipc_shutdown,
.pru_sockaddr = uipc_sockaddr,
.pru_sosend = sosend,
.pru_soreceive = soreceive,
};
accept(2) ãªã uipc_accept , listen(2) ãªã uipc_listen ã¨è¡ã£ãæãã§ ã½ã±ããã®ã·ã¹ãã ã³ã¼ã« (ã¨ã«ã¼ãã«å é¨ã®å¦ç ) ã«å¯¾å¿ããããã«ãUNIX Domain Socket ã®å®è£ ã並ãã§ããã
ããã« uipc_usrreqs 㯠struct protosw ã«åã¾ã£ã¦ãã¾ãã BSD ã«ã¼ãã«ã§ã¯ protocol-switch table ã¨å¼ã¶æ§é ä½ã®ããã§ã AF_UNIX ã§ SOCK_STREAM, SOCK_DGRAM ãå®è£ ãã¦ããã®ã uipc_usrreqs ãªã®ã ã¨çè§£ã§ãã¾ããã
static struct protosw localsw[] = { { .pr_type = SOCK_STREAM, .pr_flags = PR_CONNREQUIRED | PR_WANTRCVD | PR_RIGHTS | PR_PCBLOCK, .pr_ctloutput = uipc_ctloutput, .pr_usrreqs = &uipc_usrreqs, ð .pr_lock = unp_lock, .pr_unlock = unp_unlock, .pr_getlock = unp_getlock }, { .pr_type = SOCK_DGRAM, .pr_flags = PR_ATOMIC | PR_ADDR | PR_RIGHTS, .pr_ctloutput = uipc_ctloutput, .pr_usrreqs = &uipc_usrreqs, .pr_lock = unp_lock, .pr_unlock = unp_unlock, .pr_getlock = unp_getlock }, { .pr_ctlinput = raw_ctlinput, .pr_usrreqs = &raw_usrreqs, }, };
Linux ã§ãåæ§ã« struct proto_ops ã¨ãã颿°ãã¼ãã«ãããã¾ããã以ä¸ã¯ Linux ã® UNIX Domain Socket ã®é¢æ°ãéããæ§é ä½ã§ãã
static const struct proto_ops unix_stream_ops = { .family = PF_UNIX, .owner = THIS_MODULE, .release = unix_release, .bind = unix_bind, .connect = unix_stream_connect, .socketpair = unix_socketpair, .accept = unix_accept, .getname = unix_getname, .poll = unix_poll, .ioctl = unix_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = unix_compat_ioctl, #endif .listen = unix_listen, .shutdown = unix_shutdown, .setsockopt = sock_no_setsockopt, .getsockopt = sock_no_getsockopt, .sendmsg = unix_stream_sendmsg, .recvmsg = unix_stream_recvmsg, .mmap = sock_no_mmap, .sendpage = unix_stream_sendpage, .splice_read = unix_stream_splice_read, .set_peek_off = unix_set_peek_off, };
Linux ã«ã¯ãBSD ã® protocol-switch table ç¸å½ã®æ§é ä½ã¯ãªããã ã£ãã£ããª?
ãããã®è¨è¨ã¯ GoF ã®ãã¶ã¤ã³ãã¿ã¼ã³ã§ãã㨠Tempalte Method ãã¿ã¼ã³ã«è¿ãã®ããªã¨æã ( Strategy ãªæ°ãããã )
.... socket å¨ãã®å®è£ ã追ããããã¨ããªã¥ã¼ã ã大ãããªãéããã®ã§ ãããã§ããã¾ã
ææ³
- æ
£ããªãã½ã¼ã¹ã³ã¼ãã ã¨ã¨ã£ããããè¦ã¤ããã®ãé£ãã
sendspace
ãç¹æ®ãªååã§ãgrep ã§æ¢ãããããã¨ã§å©ãã£ã
- Linux ã¨ä¼¼ããããªè¨è¨ããã¦ããç®æã¯åã§èªã¿é²ãããã
åè
Design and Implementation of the FreeBSD Operating Systemã®å¤ãçãæã£ã¦ããã®ã§æãèªã¿ãã¾ãã ( ãã¼ãã«ãã¼ã®å¤æ¬ã ã¨å®ãã )
Mach ã¯ä»¥ä¸ã®æ¸ç±ã§ã¡ãã£ã¨ç¥èãå¾ããã¨ãããããããã§ãå¿ãã¦ãã¾ã£ããæå ã«ãæ¸ç±ãªãã£ããä¼ç¤¾ã®æ¬æ£ã«ãããã ã£ãããª
ãããã³ãã å æ°? åèã«ãªã£ãã