Home Database Mysql Tutorial memcached探索之thread model(2)

memcached探索之thread model(2)

Jun 07, 2016 pm 03:11 PM
memcached model thread under I explore

6. 下面我们看看主线程dispatch_thread的事件处理设置。在memcached.c中的main函数中 /* create unix mode sockets after dropping privileges */ if ( settings . socketpath ! = NULL ) { errno = 0 ; if ( server_socket_unix ( settings . socketpath ,

6. 下面我们看看主线程dispatch_thread的事件处理设置。在memcached.c中的main函数中

<span><font face="新宋体"><span>/* create unix mode sockets after dropping privileges */</span><br>    <span>if</span> <span>(</span>settings<span>.</span>socketpath <span>!</span><span>=</span> <span>NULL</span><span>)</span> <span>{</span><br>        <span>errno</span> <span>=</span> 0<span>;</span><br>        <span>if</span> <span>(</span>server_socket_unix<span>(</span>settings<span>.</span>socketpath<span>,</span>settings<span>.</span>access<span>)</span><span>)</span> <span>{</span><br>            vperror<span>(</span><span>"failed to listen on UNIX socket: %s"</span><span>,</span> settings<span>.</span>socketpath<span>)</span><span>;</span><br>            <span>exit</span><span>(</span>EX_OSERR<span>)</span><span>;</span><br>        <span>}</span><br>    <span>}</span><br><br>    <span>/* create the listening socket, bind it, and init */</span><br>    <span>if</span> <span>(</span>settings<span>.</span>socketpath <span>=</span><span>=</span> <span>NULL</span><span>)</span> <span>{</span><br>        <span>int</span> udp_port<span>;</span><br><br>        <span>const</span> <span>char</span> <span>*</span>portnumber_filename <span>=</span> <span>getenv</span><span>(</span><span>"MEMCACHED_PORT_FILENAME"</span><span>)</span><span>;</span><br>        <span>char</span> temp_portnumber_filename<span>[</span>PATH_MAX<span>]</span><span>;</span><br>        <span>FILE</span> <span>*</span>portnumber_file <span>=</span> <span>NULL</span><span>;</span><br><br>        <span>if</span> <span>(</span>portnumber_filename <span>!</span><span>=</span> <span>NULL</span><span>)</span> <span>{</span><br>            snprintf<span>(</span>temp_portnumber_filename<span>,</span><br>                     <span>sizeof</span><span>(</span>temp_portnumber_filename<span>)</span><span>,</span><br>                     <span>"%s.lck"</span><span>,</span> portnumber_filename<span>)</span><span>;</span><br><br>            portnumber_file <span>=</span> <span>fopen</span><span>(</span>temp_portnumber_filename<span>,</span> <span>"a"</span><span>)</span><span>;</span><br>            <span>if</span> <span>(</span>portnumber_file <span>=</span><span>=</span> <span>NULL</span><span>)</span> <span>{</span><br>                <span>fprintf</span><span>(</span><span>stderr</span><span>,</span> <span>"Failed to open \"%s\": %s\n"</span><span>,</span><br>                        temp_portnumber_filename<span>,</span> <span>strerror</span><span>(</span><span>errno</span><span>)</span><span>)</span><span>;</span><br>            <span>}</span><br>        <span>}</span><br><br>        <span>errno</span> <span>=</span> 0<span>;</span><br>        <span>if</span> <span>(</span>settings<span>.</span>port <span>&</span><span>&</span> server_socket<span>(</span>settings<span>.</span>port<span>,</span> tcp_transport<span>,</span><br>                                           portnumber_file<span>)</span><span>)</span> <span>{</span><br>            vperror<span>(</span><span>"failed to listen on TCP port %d"</span><span>,</span> settings<span>.</span>port<span>)</span><span>;</span><br>            <span>exit</span><span>(</span>EX_OSERR<span>)</span><span>;</span><br>        <span>}</span><br><br>        </font><font face="新宋体"><span>/*<br>         * initialization order: first create the listening sockets<br>         * (may need root on low ports), then drop root if needed,<br>         * then daemonise if needed, then init libevent (in some cases<br>         * descriptors created by libevent wouldn't survive forking).<br>         */</span><br>        udp_port <span>=</span> settings<span>.</span>udpport <span>?</span> settings<span>.</span>udpport <span>:</span> settings<span>.</span>port<span>;</span><br><br>        <span>/* create the UDP listening socket and bind it */</span><br>        <span>errno</span> <span>=</span> 0<span>;</span><br>        <span>if</span> <span>(</span>settings<span>.</span>udpport <span>&</span><span>&</span> server_socket<span>(</span>settings<span>.</span>udpport<span>,</span> udp_transport<span>,</span><br>                                              portnumber_file<span>)</span><span>)</span> <span>{</span><br>            vperror<span>(</span><span>"failed to listen on UDP port %d"</span><span>,</span> settings<span>.</span>udpport<span>)</span><span>;</span><br>            <span>exit</span><span>(</span>EX_OSERR<span>)</span><span>;</span><br>        <span>}</span><br><br>        <span>if</span> <span>(</span>portnumber_file<span>)</span> <span>{</span><br>            <span>fclose</span><span>(</span>portnumber_file<span>)</span><span>;</span><br>            <span>rename</span><span>(</span>temp_portnumber_filename<span>,</span> portnumber_filename<span>)</span><span>;</span><br>        <span>}</span><br>    <span>}</span><br>    <span>/* Drop privileges no longer needed */</span><br>    drop_privileges<span>(</span><span>)</span><span>;</span><br>    <span>/* enter the event loop */</span><br>    event_base_loop<span>(</span>main_base<span>,</span> 0<span>)</span><span>; //主线程(dispatcher_thread)的事件监听循环。。。</span></font></span>

<span><font face="新宋体"><span></span><br></font></span>


7. 继续跟踪server_socket函数(memcached.c中)

<span><font face="新宋体"><span>/**<br> * Create a socket and bind it to a specific port number<br> * @param port the port number to bind to<br> * @param transport the transport protocol (TCP / UDP)<br> * @param portnumber_file A filepointer to write the port numbers to<br> * when they are successfully added to the list of ports we<br> * listen on.<br> */</span><br><span>static</span> <span>int</span> server_socket<span>(</span><span>int</span> port<span>,</span> <span>enum</span> network_transport transport<span>,</span><br>                         <span>FILE</span> <span>*</span>portnumber_file<span>)</span> <span>{</span><br>    <span>int</span> sfd<span>;</span><br>    <span>struct</span> <span>linger</span> ling <span>=</span> <span>{</span>0<span>,</span> 0<span>}</span><span>;</span><br>    <span>struct</span> <span>addrinfo</span> <span>*</span>ai<span>;</span><br>    <span>struct</span> <span>addrinfo</span> <span>*</span>next<span>;</span><br>    <span>struct</span> <span>addrinfo</span> hints <span>=</span> <span>{</span> <span>.</span>ai_flags <span>=</span> <span>AI_PASSIVE</span><span>,</span><br>                              <span>.</span>ai_family <span>=</span> <span>AF_UNSPEC</span> <span>}</span><span>;</span><br>    <span>char</span> port_buf<span>[</span><span>NI_MAXSERV</span><span>]</span><span>;</span><br>    <span>int</span> <span>error</span><span>;</span><br>    <span>int</span> success <span>=</span> 0<span>;</span><br>    <span>int</span> flags <span>=</span>1<span>;</span><br><br>    hints<span>.</span>ai_socktype <span>=</span> IS_UDP<span>(</span>transport<span>)</span> <span>?</span> <span>SOCK_DGRAM</span> <span>:</span> <span>SOCK_STREAM</span><span>;</span><br><br>    <span>if</span> <span>(</span>port <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{</span><br>        port <span>=</span> 0<span>;</span><br>    <span>}</span><br>    snprintf<span>(</span>port_buf<span>,</span> <span>sizeof</span><span>(</span>port_buf<span>)</span><span>,</span> <span>"%d"</span><span>,</span> port<span>)</span><span>;</span><br>    <span>error</span><span>=</span> <span>getaddrinfo</span><span>(</span>settings<span>.</span>inter<span>,</span> port_buf<span>,</span> <span>&</span>hints<span>,</span> <span>&</span>ai<span>)</span><span>;</span><br>    <span>if</span> <span>(</span><span>error</span> <span>!</span><span>=</span> 0<span>)</span> <span>{</span><br>        <span>if</span> <span>(</span><span>error</span> <span>!</span><span>=</span> <span>EAI_SYSTEM</span><span>)</span><br>          <span>fprintf</span><span>(</span><span>stderr</span><span>,</span> <span>"getaddrinfo(): %s\n"</span><span>,</span> <span>gai_strerror</span><span>(</span><span>error</span><span>)</span><span>)</span><span>;</span><br>        <span>else</span><br>          <span>perror</span><span>(</span><span>"getaddrinfo()"</span><span>)</span><span>;</span><br>        <span>return</span> 1<span>;</span><br>    <span>}</span><br><br>    <span>for</span> <span>(</span>next<span>=</span> ai<span>;</span> next<span>;</span> next<span>=</span> next<span>-</span><span>></span>ai_next<span>)</span> <span>{</span><br>        conn <span>*</span>listen_conn_add<span>;</span><br>        <span>if</span> <span>(</span><span>(</span>sfd <span>=</span> new_socket<span>(</span>next<span>)</span><span>)</span> <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{ <span>//creat socket</span></span><br>            </font><font face="新宋体"><span>/* getaddrinfo can return "junk" addresses,<br>             * we make sure at least one works before erroring.<br>             */</span><br>            <span>continue</span><span>;</span><br>        <span>}</span><br><br><span>#</span><span>ifdef</span> IPV6_V6ONLY<br>        <span>if</span> <span>(</span>next<span>-</span><span>></span>ai_family <span>=</span><span>=</span> <span>AF_INET6</span><span>)</span> <span>{</span><br>            <span>error</span> <span>=</span> <span>setsockopt</span><span>(</span>sfd<span>,</span> <span>IPPROTO_IPV6</span><span>,</span> IPV6_V6ONLY<span>,</span> <span>(</span><span>char</span> <span>*</span><span>)</span> <span>&</span>flags<span>,</span> <span>sizeof</span><span>(</span>flags<span>)</span><span>)</span><span>;</span><br>            <span>if</span> <span>(</span><span>error</span> <span>!</span><span>=</span> 0<span>)</span> <span>{</span><br>                <span>perror</span><span>(</span><span>"setsockopt"</span><span>)</span><span>;</span><br>                <span>close</span><span>(</span>sfd<span>)</span><span>;</span><br>                <span>continue</span><span>;</span><br>            <span>}</span><br>        <span>}</span><br><span>#</span><span>endif</span><br>  <span>      </span></font></span>//setsockopt
<span><font face="新宋体">        <span>setsockopt</span><span>(</span>sfd<span>,</span> SOL_SOCKET<span>,</span> SO_REUSEADDR<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>flags<span>,</span> <span>sizeof</span><span>(</span>flags<span>)</span><span>)</span><span>; </span><br>        <span>if</span> <span>(</span>IS_UDP<span>(</span>transport<span>)</span><span>)</span> <span>{</span><br>            maximize_sndbuf<span>(</span>sfd<span>)</span><span>;</span><br>        <span>}</span> <span>else</span> <span>{</span><br>            <span>error</span> <span>=</span> <span>setsockopt</span><span>(</span>sfd<span>,</span> SOL_SOCKET<span>,</span> SO_KEEPALIVE<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>flags<span>,</span> <span>sizeof</span><span>(</span>flags<span>)</span><span>)</span><span>;</span><br>            <span>if</span> <span>(</span><span>error</span> <span>!</span><span>=</span> 0<span>)</span><br>                <span>perror</span><span>(</span><span>"setsockopt"</span><span>)</span><span>;</span><br><br>            <span>error</span> <span>=</span> <span>setsockopt</span><span>(</span>sfd<span>,</span> SOL_SOCKET<span>,</span> SO_LINGER<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>ling<span>,</span> <span>sizeof</span><span>(</span>ling<span>)</span><span>)</span><span>;</span><br>            <span>if</span> <span>(</span><span>error</span> <span>!</span><span>=</span> 0<span>)</span><br>                <span>perror</span><span>(</span><span>"setsockopt"</span><span>)</span><span>;</span><br><br>            <span>error</span> <span>=</span> <span>setsockopt</span><span>(</span>sfd<span>,</span> <span>IPPROTO_TCP</span><span>,</span> TCP_NODELAY<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>flags<span>,</span> <span>sizeof</span><span>(</span>flags<span>)</span><span>)</span><span>;</span><br>            <span>if</span> <span>(</span><span>error</span> <span>!</span><span>=</span> 0<span>)</span><br>                <span>perror</span><span>(</span><span>"setsockopt"</span><span>)</span><span>;</span><br>        <span>}</span><br>  <span>      //bind</span><br>        <span>if</span> <span>(</span><span>bind</span><span>(</span>sfd<span>,</span> next<span>-</span><span>></span>ai_addr<span>,</span> next<span>-</span><span>></span>ai_addrlen<span>)</span> <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{</span><br>            <span>if</span> <span>(</span><span>errno</span> <span>!</span><span>=</span> EADDRINUSE<span>)</span> <span>{</span><br>                <span>perror</span><span>(</span><span>"bind()"</span><span>)</span><span>;</span><br>                <span>close</span><span>(</span>sfd<span>)</span><span>;</span><br>                <span>freeaddrinfo</span><span>(</span>ai<span>)</span><span>;</span><br>                <span>return</span> 1<span>;</span><br>            <span>}</span><br>            <span>close</span><span>(</span>sfd<span>)</span><span>;</span><br>            <span>continue</span><span>;</span><br>        <span>}</span> <span>else</span> <span>{</span><br>            success<span>+</span><span>+</span><span>;</span></font></span>

<span><span></span><font face="新宋体">         <span>   //TCP listen</span><br>            <span>if</span> <span>(</span><span>!</span>IS_UDP<span>(</span>transport<span>)</span> <span>&</span><span>&</span> <span>listen</span><span>(</span>sfd<span>,</span> settings<span>.</span>backlog<span>)</span> <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{</span><br>                <span>perror</span><span>(</span><span>"listen()"</span><span>)</span><span>;</span><br>                <span>close</span><span>(</span>sfd<span>)</span><span>;</span><br>                <span>freeaddrinfo</span><span>(</span>ai<span>)</span><span>;</span><br>                <span>return</span> 1<span>;</span><br>            <span>}</span><br>            <span>if</span> <span>(</span>portnumber_file <span>!</span><span>=</span> <span>NULL</span> <span>&</span><span>&</span><br>                <span>(</span>next<span>-</span><span>></span>ai_addr<span>-</span><span>></span>sa_family <span>=</span><span>=</span> <span>AF_INET</span> <span>|</span><span>|</span><br>                 next<span>-</span><span>></span>ai_addr<span>-</span><span>></span>sa_family <span>=</span><span>=</span> <span>AF_INET6</span><span>)</span><span>)</span> <span>{</span><br>                <span>union</span> <span>{</span><br>                    <span>struct</span> <span>sockaddr_in</span> in<span>;</span><br>                    <span>struct</span> <span>sockaddr_in6</span> in6<span>;</span><br>                <span>}</span> my_sockaddr<span>;</span><br>                <span>socklen_t</span> len <span>=</span> <span>sizeof</span><span>(</span>my_sockaddr<span>)</span><span>;</span><br>                <span>if</span> <span>(</span><span>getsockname</span><span>(</span>sfd<span>,</span> <span>(</span><span>struct</span> <span>sockaddr</span><span>*</span><span>)</span><span>&</span>my_sockaddr<span>,</span> <span>&</span>len<span>)</span><span>=</span><span>=</span>0<span>)</span> <span>{</span><br>                    <span>if</span> <span>(</span>next<span>-</span><span>></span>ai_addr<span>-</span><span>></span>sa_family <span>=</span><span>=</span> <span>AF_INET</span><span>)</span> <span>{</span><br>                        <span>fprintf</span><span>(</span>portnumber_file<span>,</span> <span>"%s INET: %u\n"</span><span>,</span><br>                                IS_UDP<span>(</span>transport<span>)</span> <span>?</span> <span>"UDP"</span> <span>:</span> <span>"TCP"</span><span>,</span><br>                                <span>ntohs</span><span>(</span>my_sockaddr<span>.</span>in<span>.</span>sin_port<span>)</span><span>)</span><span>;</span><br>                    <span>}</span> <span>else</span> <span>{</span><br>                        <span>fprintf</span><span>(</span>portnumber_file<span>,</span> <span>"%s INET6: %u\n"</span><span>,</span><br>                                IS_UDP<span>(</span>transport<span>)</span> <span>?</span> <span>"UDP"</span> <span>:</span> <span>"TCP"</span><span>,</span><br>                                <span>ntohs</span><span>(</span>my_sockaddr<span>.</span>in6<span>.</span>sin6_port<span>)</span><span>)</span><span>;</span><br>                    <span>}</span><br>                <span>}</span><br>            <span>}</span><br>        <span>}</span><br><br>        <span>if</span> <span>(</span>IS_UDP<span>(</span>transport<span>)</span><span>)</span> </font><span><font face="新宋体">{ <br></font></span></span>

<font face="新宋体">            //UDP 的处理中不需要accept,所以直接派发connection到工作线程。</font><span><span></span><br><font face="新宋体">            <span>int</span> c<span>;</span><br><br>            <span>for</span> <span>(</span>c <span>=</span> 0<span>;</span> c <span> settings<span>.</span>num_threads<span>;</span> c<span>+</span><span>+</span><span>)</span> <span>{</span><br>                <span>/* this is guaranteed to hit all threads because we round-robin */</span><br>                dispatch_conn_new<span>(</span>sfd<span>,</span> conn_read<span>,</span> EV_READ <span>|</span> EV_PERSIST<span>,</span><br>                                  UDP_READ_BUFFER_SIZE<span>,</span> transport<span>)</span><span>;</span><br>            <span>}</span><br>        <span>}</span> <span>else</span> </span></font><span><font face="新宋体">{  <br></font></span></span>

<span><span><font face="新宋体">         <span> <span> //TCP的处理(注意,这里dispatcher_thread同样调用了conn_new来绑定conn_event到其main_base. 并且此时conn的初始状态为conn_listening, 事件为持久可读, 而在conn_new中注册了conn_event的回调函数为event_handler,所以,dispatche_thread在当前listen的socket可读时就会调用event_handler,进而调用driver_machine(c) 进入状态机。而在driver_machine中如果是主线程(dispatcher_thread)则会在accept socket后调用dispatch_new_conn函数来给各worker_thread派发connection...)</span></span></font></span></span><span><span></span><br><font face="新宋体">            <span>if</span> <span>(</span><span>!</span><span>(</span>listen_conn_add <span>=</span> conn_new<span>(</span>sfd<span>,</span> conn_listening<span>,</span><br>                                             EV_READ <span>|</span> EV_PERSIST<span>,</span> 1<span>,</span><br>                                             transport<span>,</span> main_base<span>)</span><span>)</span><span>)</span> <span>{</span><br>                <span>fprintf</span><span>(</span><span>stderr</span><span>,</span> <span>"failed to create listening connection\n"</span><span>)</span><span>;</span><br>                <span>exit</span><span>(</span><span>EXIT_FAILURE</span><span>)</span><span>;</span><br>            <span>}</span><br>            listen_conn_add<span>-</span><span>></span>next <span>=</span> listen_conn<span>;</span><br>            listen_conn <span>=</span> listen_conn_add<span>;</span><br>        <span>}</span><br>    <span>}</span><br><br>    <span>freeaddrinfo</span><span>(</span>ai<span>)</span><span>;</span><br><br>    <span>/* Return zero iff we detected no errors in starting up connections */</span><br>    <span>return</span> success <span>=</span><span>=</span> 0<span>;</span><br><span>}</span></font></span>


8. 看看UDP和TCP模式下dispatcher_thread都会调用的dispatch_new_conn函数(在thread.c中)

<span><font face="新宋体"><span>/*<br> * Dispatches a new connection to another thread. This is only ever called<br> * from the main thread, either during initialization (for UDP) or because<br> * of an incoming connection.<br> */</span><br><span>void</span> dispatch_conn_new<span>(</span><span>int</span> sfd<span>,</span> <span>enum</span> conn_states init_state<span>,</span> <span>int</span> event_flags<span>,</span><br>                       <span>int</span> read_buffer_size<span>,</span> <span>enum</span> network_transport transport<span>)</span> <span>{</span><br>    CQ_ITEM <span>*</span>item <span>=</span> cqi_new<span>(</span><span>)</span><span>;</span><br>    <span>int</span> tid <span>=</span> <span>(</span>last_thread <span>+</span> 1<span>)</span> <span>%</span> settings<span>.</span>num_threads<span>; //轮询的方式找worker_thread</span><br><br>    LIBEVENT_THREAD <span>*</span>thread <span>=</span> threads <span>+</span> tid<span>;</span><br><br>    last_thread <span>=</span> tid<span>;</span><br><br>    item<span>-</span><span>></span>sfd <span>=</span> sfd<span>;</span><br>    item<span>-</span><span>></span>init_state <span>=</span> init_state<span>;</span><br>    item<span>-</span><span>></span>event_flags <span>=</span> event_flags<span>;</span><br>    item<span>-</span><span>></span>read_buffer_size <span>=</span> read_buffer_size<span>;</span><br>    item<span>-</span><span>></span>transport <span>=</span> transport<span>;</span><br>  </font><span>  </span></span><span><span>//push conn到worker_thread的CQ中</span></span>
<span><font face="新宋体">    cq_push<span>(</span>thread<span>-</span><span>></span>new_conn_queue<span>,</span> item<span>)</span><span>; </span><br><br>    MEMCACHED_CONN_DISPATCH<span>(</span>sfd<span>,</span> thread<span>-</span><span>></span>thread_id<span>)</span><span>;</span><br>    <span>if</span> <span>(</span><span>write</span><span>(</span>thread<span>-</span><span>></span>notify_send_fd<span>,</span> <span>""</span><span>,</span> 1<span>)</span> <span>!</span><span>=</span> 1<span>)</span> <span>{</span><br>        <span>perror</span><span>(</span><span>"Writing to thread notify pipe"</span><span>)</span><span>;</span><br>    <span>}</span><br><span>}</span><br></font></span>


9. 先看看unix domain socket模式下主线程的事件处理设置。(在上面的6中调用的 server_socket_unix函数

<span><font face="新宋体"><span>static</span> <span>int</span> server_socket_unix<span>(</span><span>const</span> <span>char</span> <span>*</span>path<span>,</span> <span>int</span> access_mask<span>)</span> <span>{</span><br>    <span>int</span> sfd<span>;</span><br>    <span>struct</span> <span>linger</span> ling <span>=</span> <span>{</span>0<span>,</span> 0<span>}</span><span>;</span><br>    <span>struct</span> <span>sockaddr_un</span> addr<span>;</span><br>    <span>struct</span> stat tstat<span>;</span><br>    <span>int</span> flags <span>=</span>1<span>;</span><br>    <span>int</span> old_umask<span>;</span><br><br>    <span>if</span> <span>(</span><span>!</span>path<span>)</span> <span>{</span><br>        <span>return</span> 1<span>;</span><br>    <span>}</span><br><br>    <span>if</span> <span>(</span><span>(</span>sfd <span>=</span> new_socket_unix<span>(</span><span>)</span><span>)</span> <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{</span><br>        <span>return</span> 1<span>;</span><br>    <span>}</span><br><br>    </font><font face="新宋体"><span>/*<br>     * Clean up a previous socket file if we left it around<br>     */</span><br>    <span>if</span> <span>(</span>lstat<span>(</span>path<span>,</span> <span>&</span>tstat<span>)</span> <span>=</span><span>=</span> 0<span>)</span> <span>{</span><br>        <span>if</span> <span>(</span>S_ISSOCK<span>(</span>tstat<span>.</span>st_mode<span>)</span><span>)</span><br>            unlink<span>(</span>path<span>)</span><span>;</span><br>    <span>}</span><br><br>    <span>setsockopt</span><span>(</span>sfd<span>,</span> SOL_SOCKET<span>,</span> SO_REUSEADDR<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>flags<span>,</span> <span>sizeof</span><span>(</span>flags<span>)</span><span>)</span><span>;</span><br>    <span>setsockopt</span><span>(</span>sfd<span>,</span> SOL_SOCKET<span>,</span> SO_KEEPALIVE<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>flags<span>,</span> <span>sizeof</span><span>(</span>flags<span>)</span><span>)</span><span>;</span><br>    <span>setsockopt</span><span>(</span>sfd<span>,</span> SOL_SOCKET<span>,</span> SO_LINGER<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>ling<span>,</span> <span>sizeof</span><span>(</span>ling<span>)</span><span>)</span><span>;</span><br><br>    </font><font face="新宋体"><span>/*<br>     * the memset call clears nonstandard fields in some impementations<br>     * that otherwise mess things up.<br>     */</span><br>    <span>memset</span><span>(</span><span>&</span>addr<span>,</span> 0<span>,</span> <span>sizeof</span><span>(</span>addr<span>)</span><span>)</span><span>;</span><br><br>    addr<span>.</span>sun_family <span>=</span> <span>AF_UNIX</span><span>;</span><br>    <span>strncpy</span><span>(</span>addr<span>.</span>sun_path<span>,</span> path<span>,</span> <span>sizeof</span><span>(</span>addr<span>.</span>sun_path<span>)</span> <span>-</span> 1<span>)</span><span>;</span><br>    <span>assert</span><span>(</span><span>strcmp</span><span>(</span>addr<span>.</span>sun_path<span>,</span> path<span>)</span> <span>=</span><span>=</span> 0<span>)</span><span>;</span><br>    old_umask <span>=</span> umask<span>(</span> <span>~</span><span>(</span>access_mask<span>&</span>0777<span>)</span><span>)</span><span>;</span><br>    <span>if</span> <span>(</span><span>bind</span><span>(</span>sfd<span>,</span> <span>(</span><span>struct</span> <span>sockaddr</span> <span>*</span><span>)</span><span>&</span>addr<span>,</span> <span>sizeof</span><span>(</span>addr<span>)</span><span>)</span> <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{</span><br>        <span>perror</span><span>(</span><span>"bind()"</span><span>)</span><span>;</span><br>        <span>close</span><span>(</span>sfd<span>)</span><span>;</span><br>        umask<span>(</span>old_umask<span>)</span><span>;</span><br>        <span>return</span> 1<span>;</span><br>    <span>}</span><br>    umask<span>(</span>old_umask<span>)</span><span>;</span><br>    <span>if</span> <span>(</span><span>listen</span><span>(</span>sfd<span>,</span> settings<span>.</span>backlog<span>)</span> <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{</span><br>        <span>perror</span><span>(</span><span>"listen()"</span><span>)</span><span>;</span><br>        <span>close</span><span>(</span>sfd<span>)</span><span>;</span><br>        <span>return</span> 1<span>;</span><br>    <span>}</span><br>    <span>if</span> <span>(</span><span>!</span><span>(</span>listen_conn <span>=</span> conn_new<span>(</span>sfd<span>,</span> conn_listening<span>, //同样是调用conn_new</span><br>                                 EV_READ <span>|</span> EV_PERSIST<span>,</span> 1<span>,</span><br>                                 local_transport<span>,</span> main_base<span>)</span><span>)</span><span>)</span> <span>{</span><br>        <span>fprintf</span><span>(</span><span>stderr</span><span>,</span> <span>"failed to create listening connection\n"</span><span>)</span><span>;</span><br>        <span>exit</span><span>(</span><span>EXIT_FAILURE</span><span>)</span><span>;</span><br>    <span>}</span><br><br>    <span>return</span> 0<span>;</span><br><span>}</span></font><br></span>


Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat Commands and How to Use Them
1 months ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Revealing the secrets of canvas properties Revealing the secrets of canvas properties Jan 17, 2024 am 10:08 AM

To explore the secrets of the canvas attribute, you need specific code examples. Canvas is a very powerful graphics drawing tool in HTML5. Through it, we can easily draw complex graphics, dynamic effects, games, etc. in web pages. However, in order to use it, we must be familiar with the related properties and methods of Canvas and master how to use them. In this article, we will explore some of the core properties of Canvas and provide specific code examples to help readers better understand how these properties should be used.

Explore the future development trends of Go language Explore the future development trends of Go language Mar 24, 2024 pm 01:42 PM

Title: Exploring the future development trends of Go language With the rapid development of Internet technology, programming languages ​​are also constantly evolving and improving. Among them, as an open source programming language developed by Google, Go language (Golang) is highly sought after for its simplicity, efficiency and concurrency features. As more and more companies and developers begin to adopt Go language to build applications, the future development trend of Go language has attracted much attention. 1. Characteristics and advantages of Go language Go language is a statically typed programming language with garbage collection mechanism and

Exploration of commonly used database selections in Go language Exploration of commonly used database selections in Go language Jan 28, 2024 am 08:04 AM

Explore commonly used database selections in Go language Introduction: In modern software development, whether it is web applications, mobile applications or Internet of Things applications, data storage and query are inseparable. In the Go language, we have many excellent database options. This article will explore commonly used database choices in the Go language and provide specific code examples to help readers understand and choose a database that suits their needs. 1. SQL database MySQL MySQL is a popular open source relational database management system. It supports a wide range of features and

Trezor Cold Wallet: Model One and Model T Features and Usage Guide Trezor Cold Wallet: Model One and Model T Features and Usage Guide Jan 19, 2024 pm 04:12 PM

After problems occurred in many centralized exchanges, more and more cryptocurrency investors began to transfer assets to cold wallets to reduce the risks posed by centralized exchanges. This article will introduce Trezor, the world's earliest cold wallet provider. Since the first cold wallet was launched in 2014, it has been sold in many countries around the world. Trezor's products include Model One launched in 2014 and the advanced version Model T launched in 2018. The following will continue to introduce the differences between these two products and other cold wallets. What is Trezor cold wallet? In 2014, Trezor launched the first cold wallet ModelOne. In addition to common BTC, ETH, USDT and other currencies, the wallet also supports more than 1,000 other currencies.

Exploring Graph Programming in Go: Possibilities of Implementing Graph APIs Exploring Graph Programming in Go: Possibilities of Implementing Graph APIs Mar 25, 2024 am 11:03 AM

Exploring graphics programming in Go language: the possibility of implementing graphics APIs With the continuous development of computer technology, graphics programming has become an important application field in computer science. Through graphics programming, we can realize various exquisite graphical interfaces, animation effects and data visualization, providing users with a more intuitive and friendly interactive experience. With the rapid development of Go language in recent years, more and more developers have begun to turn their attention to the application of Go language in the field of graphics programming. In this article, we will explore implementing

I am going to travel to Tibet with a backpack. ① How many liters of bag is suitable for me to carry? Please tell me what you think is the best configuration. I am 170 and have good physical strength for the first time. I am going to travel to Tibet with a backpack. ① How many liters of bag is suitable for me to carry? Please tell me what you think is the best configuration. I am 170 and have good physical strength for the first time. Jan 07, 2024 am 10:06 AM

I am planning to go backpacking in Tibet. ① How many liters of bag should I carry? Please tell me what you think is the best configuration. I am 170 and have good physical strength. The first time I went hiking, the amount was 60 liters or more. The amount of hiking was less than 60 liters. The entire journey was by car. You don’t need a backpack, a suitcase is more convenient. If you really need to carry something with you, a 25-40 liter bag is more than enough. Necessary supplies for Tibet travel: sunglasses, sun hat, sunscreen, skin cream, lip balm, long-sleeved top, Sweater; for special travel or travel to Ali, northern Tibet, and Sichuan-Tibet line, it is recommended to bring: sleeping bag (cold protection), sheets (dirty protection), down jacket, travel shoes or hiking shoes, slippers, toothbrush, toothpaste, towel, rolling paper , paper underwear, disinfectant wipes, flashlight, waterproof matches, knives, rope. Can a computer be carried in the front bag? Can a computer be carried in the front bag? Some backpacks have it.

A deep dive into kernel panic: why it protects your system A deep dive into kernel panic: why it protects your system Dec 29, 2023 am 09:08 AM

Explore KernelPanic: Why it is a system protection mechanism, specific code examples are needed Introduction: In computer systems, KernelPanic (kernel panic) is a system protection mechanism that forces the operating system to enter an abnormal state when it encounters an unsolvable problem. Termination status. When the operating system cannot guarantee its normal operation, the computer will display an error message similar to "KernelPanic" and stop running. This article will explore the principles and mechanisms behind KernelPanic.

An in-depth exploration of the Linux kernel source code distribution An in-depth exploration of the Linux kernel source code distribution Mar 15, 2024 am 10:21 AM

This is a 1500-word article that explores the Linux kernel source code distribution in depth. Due to limited space, we will focus on the organizational structure of the Linux kernel source code and provide some specific code examples to help readers better understand. The Linux kernel is an open source operating system kernel whose source code is hosted on GitHub. The entire Linux kernel source code distribution is very large, containing hundreds of thousands of lines of code, involving multiple different subsystems and modules. To gain a deeper understanding of the Linux kernel source code

See all articles