網絡子係統84_sock事件通知進程
// socket初始化 // 調用路徑:inet_create->sock_init_data 1.1 void sock_init_data(struct socket *sock, struct sock *sk) { ... //sock狀態改變的回調函數,當sock的狀態變遷(如從established到close_wait)就會調用這個函數 sk->sk_state_change = sock_def_wakeup; //sock有輸入數據的時被調用 sk->sk_data_ready = sock_def_readable; //sock有可寫空間時被調用 sk->sk_write_space = sock_def_write_space; //sock出錯(如收到一個rst)會被調 sk->sk_error_report = sock_def_error_report; sk->sk_destruct = sock_def_destruct; ... } // 喚醒sock上阻塞的進程 // 步驟: // 1.檢查struct sock->sk_wq上是否有阻塞的進程 // 1.2 喚醒struct sock->sk_wq上的進程 2.1 static void sock_def_wakeup(struct sock *sk) { struct socket_wq *wq; rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); if (wq_has_sleeper(wq)) wake_up_interruptible_all(&wq->wait); rcu_read_unlock(); } // 有可用輸入數據 // 調用路徑:raw_local_deliver->sock_def_readable // 步驟: // 1.檢查struct sock->sk_wq上是否有阻塞的進程 // 1.1 喚醒struct sock->sk_wq上的進程 // 2.喚醒在用戶空間設置了信號io的進程 2.2 static void sock_def_readable(struct sock *sk, int len) { struct socket_wq *wq; rcu_read_lock(); //sock的wait_queue wq = rcu_dereference(sk->sk_wq); //喚醒在wait_queue上等待可用數據的進程 if (wq_has_sleeper(wq)) wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND); //處理O_ASYNC sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); rcu_read_unlock(); } // 有可用輸出空間 // 步驟: // 1.判斷是否有足夠可用內存 // 1.1 空閑內存量 >= 50% // 2.喚醒在wait_queue上等待可用內存的進程 // 3.處理信號io 2.3 static void sock_def_write_space(struct sock *sk) { struct socket_wq *wq; rcu_read_lock(); //判斷是否有足夠內存 // 可用內存>=50% if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { wq = rcu_dereference(sk->sk_wq); //喚醒wait_queue上的進程 if (wq_has_sleeper(wq)) wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | POLLWRNORM | POLLWRBAND); //處理信號io if (sock_writeable(sk)) sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); } rcu_read_unlock(); } // sock發生錯誤 // 1. 檢查sock上是否有進程在阻塞 // 1.1 喚醒進程有錯誤發生 // 2. 處理信號io 2.4 static void sock_def_error_report(struct sock *sk) { struct socket_wq *wq; rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); if (wq_has_sleeper(wq)) wake_up_interruptible_poll(&wq->wait, POLLERR); sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); rcu_read_unlock(); }
最後更新:2017-04-03 12:55:18