日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

accept系统调用内核实现

發(fā)布時間:2025/7/14 windows 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 accept系统调用内核实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
用戶態(tài)對accept的標準使用方法: if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size)) == -1){//accept()函數(shù)讓server接收客戶的連接請求perror("accept Error\n");continue;} sockfd是通過socket系統(tǒng)調(diào)用,而且經(jīng)過listen過的套接字: sockfd = socket(AF_INET, SOCK_STREAM, 0) listen(sockfd, 128)remote_addr將會存儲遠端設備的地址信息。/** For accept, we attempt to create a new socket, set up the link* with the client, wake up the client, then return the new* connected fd. We collect the address of the connector in kernel* space and move it to user at the very end. This is unclean because* we open the socket then return an error.** 1003.1g adds the ability to recvmsg() to query connection pending* status to recvmsg. We need to add that support in a way thats* clean when we restucture accept also.*/asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,int __user *upeer_addrlen) {struct socket *sock, *newsock;struct file *newfile;int err, len, newfd, fput_needed;char address[MAX_SOCK_ADDR];//通過監(jiān)聽套接字的描寫敘述符fd,找到監(jiān)聽套接字sock = sockfd_lookup_light(fd, &err, &fput_needed);if (!sock)goto out;err = -ENFILE; //創(chuàng)建新的socket,即心的套接字,它將被client_fd 描寫敘述,用于數(shù)據(jù)傳輸, //也就是accept系統(tǒng)調(diào)用返回值client_fd 所相應的套接口if (!(newsock = sock_alloc()))goto out_put;//繼承l(wèi)isten_fd相應的的一些屬性,包含套接字類型,和操作。 //不難理解,listen_fd和client_fd 相應的套接口都是tcp,這些不用一一賦值,直接用listen_fd的屬性就可以。newsock->type = sock->type;newsock->ops = sock->ops;/** We don't need try_module_get here, as the listening socket (sock)* has the protocol module (sock->ops->owner) held.*/ //不懂__module_get(newsock->ops->owner);//創(chuàng)建新的file,然后返回newfd ,這個fd就是待會被返回的client_fd //到如今為止,這個newfd和newfile是有關聯(lián)的。newfd = sock_alloc_fd(&newfile);if (unlikely(newfd < 0)) {err = newfd;sock_release(newsock);goto out_put;} //使得這個newsock綁定剛才新建的newfile //即如今為止,newfd newfile newsock之間是有關聯(lián)的err = sock_attach_fd(newsock, newfile);if (err < 0)goto out_fd_simple;err = security_socket_accept(sock, newsock);if (err)goto out_fd; //newsock是socket結(jié)構體,sock->ops->accept的目的是為newsock關聯(lián)一個sock結(jié)構體 //即三次握手結(jié)束后,新建的sock傳輸控制塊,它等待用戶accept系統(tǒng)調(diào)用“領養(yǎng)”它。 //sock->ops->accept相應的函數(shù)是inet_accepterr = sock->ops->accept(sock, newsock, sock->file->f_flags);if (err < 0)goto out_fd;if (upeer_sockaddr) {if (newsock->ops->getname(newsock, (struct sockaddr *)address,&len, 2) < 0) {err = -ECONNABORTED;goto out_fd;}err = move_addr_to_user(address, len, upeer_sockaddr,upeer_addrlen);if (err < 0)goto out_fd;} ......................................... }/** Accept a pending connection. The TCP layer now gives BSD semantics.*/ int inet_accept(struct socket *sock, struct socket *newsock, int flags) { //第一個參數(shù)sock是監(jiān)聽套接字代表的套接字 //newsock是剛才我們新建的套接字,用以描寫敘述數(shù)據(jù)傳輸 //顯然,此函數(shù)的目的,是找到通過套接字,找到套接字上掛著的以及完畢三次握手的sk //這個被找到的sk,將被關聯(lián)到newsock//sk1 是監(jiān)聽套接字相應的傳輸控制塊struct sock *sk1 = sock->sk;int err = -EINVAL;//sk2(三次握手后建立的傳輸控制塊) 是掛在sk1(監(jiān)聽套接字的傳輸控制塊) 中的完畢三次握手后的sk // sk1->sk_prot->accept 相應的函數(shù)是inet_csk_acceptstruct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err);if (!sk2)goto do_err;lock_sock(sk2);WARN_ON(!((1 << sk2->sk_state) &(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE)));//這個被找到的sk,將被關聯(lián)到newsock //三次握手后建立的傳輸控制塊sk(sock 結(jié)構體),是不正確應不論什么socket結(jié)構體的,所以我們關聯(lián)上 //這樣三次握手后建立的傳輸控制塊sk,就和文件系統(tǒng)有關聯(lián)了 //關聯(lián)上后,我們就能對其調(diào)用send,recvfrom等系統(tǒng)調(diào)用了sock_graft(sk2, newsock);newsock->state = SS_CONNECTED;err = 0;release_sock(sk2); do_err:return err; }/** This will accept the next outstanding connection.*/ //inet_csk_accept的功能時獲取建立3次握手后的sk,一次調(diào)用返回一個sk struct sock *inet_csk_accept(struct sock *sk, int flags, int *err) { //第一個參數(shù)是監(jiān)聽套接字相應的傳輸控制塊。struct inet_connection_sock *icsk = inet_csk(sk);struct sock *newsk;int error;lock_sock(sk);/* We need to make sure that this socket is listening,* and that it has something pending.*/error = -EINVAL; //假設你傳進的參數(shù)正確,監(jiān)聽套接字相應的傳輸控制塊的狀態(tài),肯定是TCP_LISTENif (sk->sk_state != TCP_LISTEN)goto out_err;/* Find already established connection */ //icsk->icsk_accept_queue掛的是request_sock,request_sock上掛的就是三次握手后新建的sk //reqsk_queue_empty(&icsk->icsk_accept_queue)推斷是否空,就進入if,怎樣設置為堵塞,則休眠if (reqsk_queue_empty(&icsk->icsk_accept_queue)) {long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);/* If this is a non blocking socket don't sleep */error = -EAGAIN;if (!timeo)goto out_err;error = inet_csk_wait_for_connect(sk, timeo);if (error)goto out_err;}//reqsk_queue_get_child的邏輯是: //1:取出icsk_accept_queue的request_sock,然后取出request_sock中的sk //2:listen的sk中,sk_ack_backlog計數(shù)減一,sk->sk_ack_backlog--,由于sk_ack_backlog有上限。 //3:刪除request_sock //4:return取出的sknewsk = reqsk_queue_get_child(&icsk->icsk_accept_queue, sk);WARN_ON(newsk->sk_state == TCP_SYN_RECV); out:release_sock(sk);return newsk; out_err:newsk = NULL;*err = error;goto out; }

轉(zhuǎn)載于:https://www.cnblogs.com/mfrbuaa/p/3901351.html

總結(jié)

以上是生活随笔為你收集整理的accept系统调用内核实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。