0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

淺析Linux內(nèi)核數(shù)調(diào)用過(guò)程

冬至子 ? 來(lái)源:Linux碼農(nóng) ? 作者:Linux碼農(nóng) ? 2022-11-16 16:25 ? 次閱讀

應(yīng)用程序順序調(diào)用接收數(shù)進(jìn)行接收數(shù)數(shù)據(jù)時(shí),內(nèi)核數(shù)調(diào)用過(guò)程如下

sys_recv
 -> sys_recvfrom
    -> sock_recvmsg  
       -> __sock_recvmsg
          -> sock->ops->recvmsg => sock_common_recvmsg
             -> sk->sk_prot->recvmsg => tcp_recvmsg

最后協(xié)議棧通過(guò)調(diào) 使用tcp_recvmsg 從接收隊(duì)列中獲取數(shù)據(jù)采集到用戶文件夾中。

圖片

tcp_recvmsg

//把數(shù)據(jù)從接收隊(duì)列中復(fù)制到用戶空間中
int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        size_t len, int nonblock, int flags, int *addr_len)
{
    struct tcp_sock *tp = tcp_sk(sk);
    int copied = 0;
    u32 peek_seq;
    u32 *seq;
    unsigned long used;
    int err;
    int target;     /* Read at least this many bytes */
    long timeo;
    struct task_struct *user_recv = NULL;
    int copied_early = 0;
    //先對(duì)傳輸層上鎖,以免在讀的過(guò)程中,軟中斷操作傳輸層,對(duì)數(shù)據(jù)不同步造成后果
    lock_sock(sk);

    TCP_CHECK_TIMER(sk);
    //初始化錯(cuò)誤碼
    err = -ENOTCONN;
    //TCP_LISTEN狀態(tài) 不允許讀
    if (sk->sk_state == TCP_LISTEN)
        goto out;

     // 獲取阻塞超時(shí)時(shí)間,若非阻塞讀取,超時(shí)時(shí)間為0
    timeo = sock_rcvtimeo(sk, nonblock);

    /* Urgent data needs to be handled specially. */
    ///若讀取外帶數(shù)據(jù),則跳轉(zhuǎn)處理
    if (flags & MSG_OOB)
        goto recv_urg;

    /*判斷是從緩沖區(qū)讀取數(shù)據(jù)還是只是查看數(shù)據(jù): 若是讀取數(shù)據(jù)到用戶空間,會(huì)更新copied_seq,
    而只是查看數(shù)據(jù),不需更新copied_seq,所以在這里先判斷是讀緩沖區(qū)數(shù)據(jù)還是只是查看數(shù)據(jù)*/
    seq = &tp->copied_seq;
    if (flags & MSG_PEEK) {
        peek_seq = tp->copied_seq;
        seq = &peek_seq;
    }

    /* 根據(jù)是否設(shè)置MSG_WAITALL來(lái)確定本次調(diào)用需要接收數(shù)據(jù)的長(zhǎng)度,
    若設(shè)置該標(biāo)志,則讀取數(shù)據(jù)的長(zhǎng)度為用戶調(diào)用時(shí)的輸入參數(shù)len */
    target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);


    do {
        struct sk_buff *skb;
        u32 offset;

        /* Are we at urgent data? Stop if we have read anything or have SIGURG pending. 
           通過(guò)urg_data 和 urg_seq 來(lái)檢測(cè)當(dāng)前是否讀取到外帶數(shù)據(jù)。
        */
        if (tp->urg_data && tp->urg_seq == *seq) {
            //若在讀取到外帶數(shù)據(jù)之前已經(jīng)讀取了部分?jǐn)?shù)據(jù),則終止本次正常數(shù)據(jù)的讀取。
            if (copied)
                break;
            //若用戶進(jìn)程有信號(hào)待處理,則也終止本次的讀取
            if (signal_pending(current)) {
                copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
                break;
            }
        }

        /* Next get a buffer. */
        //獲取下一個(gè)待讀取的段
        skb = skb_peek(&sk->sk_receive_queue);
        do {
            //若隊(duì)列為空,這只能接著處理prequeue或后備隊(duì)列
            if (!skb)
                break;

            /* Now that we have two receive queues this
             * shouldn't happen.
             */
            //若接收隊(duì)列中段序號(hào)大,說(shuō)明也獲取不到待讀取的段,只能接著處理prequeue或后備隊(duì)列
            if (before(*seq, TCP_SKB_CB(skb)->seq)) {
                printk(KERN_INFO "recvmsg bug: copied %X "
                       "seq %X\\n", *seq, TCP_SKB_CB(skb)->seq);
                break;
            }
            //計(jì)算該段讀取數(shù)據(jù)的偏移位置,該偏移位置必須在該段的數(shù)據(jù)長(zhǎng)度范圍內(nèi)才有效
            offset = *seq - TCP_SKB_CB(skb)->seq;
            ///SYN標(biāo)志占用了一個(gè)序號(hào),因此若存在SYN,則調(diào)整偏移
            if (skb->h.th->syn)
                offset--;
            //偏移位置必須在該段的數(shù)據(jù)長(zhǎng)度范圍內(nèi)才有效
            if (offset < skb->len)
                goto found_ok_skb;
            //若存在fin標(biāo)志,跳轉(zhuǎn)處理
            if (skb->h.th->fin)
                goto found_fin_ok;
            BUG_TRAP(flags & MSG_PEEK);
            skb = skb->next;
        } while (skb != (struct sk_buff *)&sk->sk_receive_queue);

        /* Well, if we have backlog, try to process it now yet. */
        //只有在讀取完數(shù)據(jù)后,才能在后備隊(duì)列不為空的情況下,去處理接收到后備隊(duì)列中的tcp段,否則終止本次讀取
        if (copied >= target && !sk->sk_backlog.tail)
            break;
        /*接收隊(duì)列中可讀的段已讀完,在處理prequeue或后備隊(duì)列之前需要檢測(cè)是否有導(dǎo)致返回的事件、狀態(tài)等*/

        if (copied) {
            if (sk->sk_err || //有錯(cuò)誤發(fā)送
                sk->sk_state == TCP_CLOSE ||
                (sk->sk_shutdown & RCV_SHUTDOWN) || //shutdown后不允許接收數(shù)據(jù)
                !timeo || //非阻塞
                signal_pending(current) || //收到信號(hào)
                (flags & MSG_PEEK)) //只是查看數(shù)據(jù)
                break; //上面檢測(cè)條件只要有成立立即退出本次讀取
        } else {
            //檢測(cè)tcp會(huì)話是否即將終結(jié)
            if (sock_flag(sk, SOCK_DONE))
                break;
            ///有錯(cuò)誤發(fā)生,返回錯(cuò)誤碼
            if (sk->sk_err) {
                copied = sock_error(sk);
                break;
            }

            if (sk->sk_shutdown & RCV_SHUTDOWN)
                break;
            //tcp狀態(tài)處于close,而套接口不在終結(jié)狀態(tài),則進(jìn)程可能是在讀一個(gè)沒有建立起連接的套接口,則返回ENOTCONN
            if (sk->sk_state == TCP_CLOSE) {
                if (!sock_flag(sk, SOCK_DONE)) {
                    /* This occurs when user tries to read
                     * from never connected socket.
                     */
                    copied = -ENOTCONN;
                    break;
                }
                break;
            }
            //未讀到數(shù)據(jù),且是非阻塞讀,返回EAGAIN
            if (!timeo) {
                copied = -EAGAIN;
                break;
            }
            //檢測(cè)是否收到數(shù)據(jù),同時(shí)獲取相應(yīng)的錯(cuò)誤碼
            if (signal_pending(current)) {
                copied = sock_intr_errno(timeo);
                break;
            }
        }
        //檢測(cè)是否有確認(rèn)需要立即發(fā)送
        tcp_cleanup_rbuf(sk, copied);

        //在未啟用sysctl_tcp_low_latency情況下,檢查tcp_low_latency,默認(rèn)其為0,表示使用prequeue隊(duì)列
        if (!sysctl_tcp_low_latency && tp->ucopy.task == user_recv) {
            /* Install new reader */
            /*若是本次讀取的第一此檢測(cè)處理prequeue隊(duì)列,則需要設(shè)置正在讀取的進(jìn)程描述符、緩存地址信息。這樣當(dāng)
            讀取進(jìn)程進(jìn)入睡眠后,ESTABLISHED狀態(tài)的接收處理就可能直接把數(shù)據(jù)復(fù)制到用戶空間*/
            if (!user_recv && !(flags & (MSG_TRUNC | MSG_PEEK))) {
                user_recv = current;
                tp->ucopy.task = user_recv;
                tp->ucopy.iov = msg->msg_iov;
            }
            //更新當(dāng)前可以使用的用戶緩存大小
            tp->ucopy.len = len;

            BUG_TRAP(tp->copied_seq == tp->rcv_nxt ||
                 (flags & (MSG_PEEK | MSG_TRUNC)));


            //若prequeue不為空,跳轉(zhuǎn)處理prequeue隊(duì)列
            if (!skb_queue_empty(&tp->ucopy.prequeue))
                goto do_prequeue;

            /* __ Set realtime policy in scheduler __ */
        }
        //若數(shù)據(jù)讀取完,調(diào)用release_sock 解鎖傳輸控制塊,主要用來(lái)處理后備隊(duì)列
        if (copied >= target) {
            /* Do not sleep, just process backlog. */
            release_sock(sk);
            //鎖定傳輸控制塊,在調(diào)用lock_sock時(shí)進(jìn)程可能會(huì)出現(xiàn)睡眠
            lock_sock(sk);
        } else
            /*若數(shù)據(jù)未讀取,且是阻塞讀取,則進(jìn)入睡眠等待接收數(shù)據(jù)。在這種情況下,tcp_v4_do_rcv處理
              tcp段時(shí)可能會(huì)把數(shù)據(jù)直接復(fù)制到用戶空間*/
            sk_wait_data(sk, &timeo);



        if (user_recv) {
            int chunk;

            /* __ Restore normal policy in scheduler __ */
            //更新剩余的用戶空間長(zhǎng)度和已復(fù)制到用戶空間的數(shù)據(jù)長(zhǎng)度
            if ((chunk = len - tp->ucopy.len) != 0) {
                NET_ADD_STATS_USER(LINUX_MIB_TCPDIRECTCOPYFROMBACKLOG, chunk);
                len -= chunk;
                copied += chunk;
            }
            /*若接收到接收隊(duì)列中的數(shù)據(jù)已經(jīng)全部復(fù)制到用戶進(jìn)程空間,但prequeue隊(duì)列不為空,則需繼續(xù)處理prequeue隊(duì)列,
            并更新剩余的用戶空間長(zhǎng)度和已復(fù)制到用戶空間的數(shù)據(jù)長(zhǎng)度*/
            if (tp->rcv_nxt == tp->copied_seq &&
                !skb_queue_empty(&tp->ucopy.prequeue)) {
do_prequeue:
                tcp_prequeue_process(sk);

                if ((chunk = len - tp->ucopy.len) != 0) {
                    NET_ADD_STATS_USER(LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE, chunk);
                    len -= chunk;
                    copied += chunk;
                }
            }
        }
        //處理完prequeue隊(duì)列后,若有更新copied_seq,且只是查看數(shù)據(jù),則需要更新peek_seq
        if ((flags & MSG_PEEK) && peek_seq != tp->copied_seq) {
            if (net_ratelimit())
                printk(KERN_DEBUG "TCP(%s:%d): Application bug, race in MSG_PEEK.\\n",
                       current->comm, current->pid);
            peek_seq = tp->copied_seq;
        }
        //繼續(xù)獲取下一個(gè)待讀取的段作處理
        continue;

    found_ok_skb:
        /* Ok so how much can we use? */
        /*獲取該可讀取段的數(shù)據(jù)長(zhǎng)度,在前面的處理中已由tcp序號(hào)得到本次讀取數(shù)據(jù)在該段中的偏移offset*/
        used = skb->len - offset;
        if (len < used)
            used = len;

        /* Do we have urgent data here? */
        //若段內(nèi)包含帶外數(shù)據(jù),則獲取帶外數(shù)據(jù)在該段中的偏移
        if (tp->urg_data) {
            u32 urg_offset = tp->urg_seq - *seq;
            if (urg_offset < used) {
                //若偏移為0,說(shuō)明目前需要的數(shù)據(jù)正是帶外數(shù)據(jù),且?guī)鈹?shù)據(jù)不允許進(jìn)入正常的數(shù)據(jù)流
                if (!urg_offset) {
                    if (!sock_flag(sk, SOCK_URGINLINE)) {
                        ++*seq;
                        offset++;
                        used--;
                        if (!used)
                            goto skip_copy;
                    }
                } else
                    //若偏移不為0,則需要調(diào)整本次讀取的正常數(shù)據(jù)長(zhǎng)度直到讀到帶外數(shù)據(jù)為止
                    used = urg_offset;
            }
        }
        //處理讀取數(shù)據(jù)的情況
        if (!(flags & MSG_TRUNC)) {
            {
                //將數(shù)據(jù)復(fù)制到用戶空間
                err = skb_copy_datagram_iovec(skb, offset,
                        msg->msg_iov, used);
                if (err) {
                    /* Exception. Bailout! */
                    if (!copied)
                        copied = -EFAULT;
                    break;
                }
            }
        }

        *seq += used; //調(diào)整已讀取數(shù)據(jù)的序號(hào)
        copied += used;//調(diào)整已讀取數(shù)據(jù)的長(zhǎng)度
        len -= used;//調(diào)整剩余的可用空間緩存大小

        //調(diào)整合理的tcp接收緩沖區(qū)大小
        tcp_rcv_space_adjust(sk);

skip_copy:
        //若對(duì)帶外數(shù)據(jù)處理完畢,則將標(biāo)志清零,
        if (tp->urg_data && after(tp->copied_seq, tp->urg_seq)) {
            tp->urg_data = 0;
            //設(shè)置首部標(biāo)志,下一個(gè)接收段又可以通過(guò)首部預(yù)測(cè)執(zhí)行快慢速路徑
            tcp_fast_path_check(sk, tp);
        }
        //若該段還有數(shù)據(jù)未讀取(如帶外數(shù)據(jù)),則是能繼續(xù)處理該段,而不能把該段從接收隊(duì)列中刪除
        if (used + offset < skb->len)
            continue;

        if (skb->h.th->fin)
            goto found_fin_ok;
        if (!(flags & MSG_PEEK)) {
            sk_eat_skb(sk, skb, copied_early);
            copied_early = 0;
        }
        //繼續(xù)處理后續(xù)的段
        continue;

    found_fin_ok:
        /* Process the FIN. */
        //由于fin標(biāo)志占用一個(gè)序號(hào),因此當(dāng)前讀取的序號(hào)需遞增
        ++*seq;
        if (!(flags & MSG_PEEK)) {
            sk_eat_skb(sk, skb, copied_early);
            copied_early = 0;
        }
        //接收到fin標(biāo)志,無(wú)需繼續(xù)處理后續(xù)的段
        break;
    } while (len > 0);

    if (user_recv) {
        //不空,處理prequeue
        if (!skb_queue_empty(&tp->ucopy.prequeue)) {
            int chunk;

            tp->ucopy.len = copied > 0 ? len : 0;

            tcp_prequeue_process(sk);
            //若在處理prequeue隊(duì)列過(guò)程中又有一部分?jǐn)?shù)據(jù)復(fù)制到用戶空間,則調(diào)整剩余的可用空間緩存大小和已讀數(shù)據(jù)的序號(hào)
            if (copied > 0 && (chunk = len - tp->ucopy.len) != 0) {
                NET_ADD_STATS_USER(LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE, chunk);
                len -= chunk;
                copied += chunk;
            }
        }

    /*清零,表示用戶當(dāng)前沒有讀取數(shù)據(jù)。這樣當(dāng)處理prequeue隊(duì)列時(shí)不會(huì)將數(shù)據(jù)復(fù)制到用戶空間,
        因?yàn)橹挥性谖磫⒂胻cp_low_latency下,用戶主動(dòng)讀取時(shí),才有機(jī)會(huì)將數(shù)據(jù)直接復(fù)制到用戶空間*/
        tp->ucopy.task = NULL;
        tp->ucopy.len = 0;
    }


    /*在完成讀取數(shù)據(jù)后,需再次檢測(cè)是否有必要立即發(fā)送ack,并根據(jù)情況確定是否發(fā)送ack段*/
    tcp_cleanup_rbuf(sk, copied);

    TCP_CHECK_TIMER(sk);
    //返回前解鎖傳輸控制塊
    release_sock(sk);
    //返回已讀取的字節(jié)數(shù)
    return copied;

/*若在讀取過(guò)程中發(fā)生了錯(cuò)誤,則會(huì)跳轉(zhuǎn)到此,解鎖傳輸層后返回錯(cuò)誤碼*/
out:
    TCP_CHECK_TIMER(sk);
    release_sock(sk);
    return err;

/*若是接收帶外數(shù)據(jù),則調(diào)用tcp_recv_urg接收*/
recv_urg:
    err = tcp_recv_urg(sk, timeo, msg, len, flags, addr_len);
    goto out;
}

以上調(diào)使用排除帶外數(shù)據(jù)只分析正常的數(shù)據(jù)的話,處理過(guò)程如下:

1、根據(jù)尚未從內(nèi)核空間復(fù)制到用戶空間的最前面一個(gè)字節(jié)的序號(hào),找到待貝的數(shù)據(jù)塊。

2、將數(shù)據(jù)從數(shù)據(jù)塊中選擇貝到用戶空間。

3、調(diào)整合理的TCP接收綁定沖區(qū)大小

4、跳到第一步循環(huán)處理,直達(dá)到滿足用戶讀取數(shù)量的條件。

審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • TCP
    TCP
    +關(guān)注

    關(guān)注

    8

    文章

    1337

    瀏覽量

    78874
  • LINUX內(nèi)核
    +關(guān)注

    關(guān)注

    1

    文章

    316

    瀏覽量

    21584
  • ADD
    ADD
    +關(guān)注

    關(guān)注

    1

    文章

    20

    瀏覽量

    9386
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    C語(yǔ)言函數(shù)調(diào)用過(guò)程中的內(nèi)存變化解析

    相信很多編程新手村的同學(xué)們都會(huì)有一個(gè)疑問(wèn):C 語(yǔ)言如何調(diào)用函數(shù)的呢?局部變量的作用域?yàn)槭裁磧H限于函數(shù)內(nèi)?這個(gè)調(diào)用不是指C 語(yǔ)言上的函數(shù)調(diào)用的語(yǔ)法,而是在內(nèi)存的視角下,函數(shù)的調(diào)用過(guò)程。本
    的頭像 發(fā)表于 12-11 16:21 ?3701次閱讀

    Linux內(nèi)核的編譯主要過(guò)程

    Linux內(nèi)核的編譯主要過(guò)程: 配置、編譯、安裝 。
    發(fā)表于 08-08 16:02 ?685次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>的編譯主要<b class='flag-5'>過(guò)程</b>

    Linux內(nèi)核中系統(tǒng)調(diào)用詳解

    Linux內(nèi)核中設(shè)置了一組用于實(shí)現(xiàn)各種系統(tǒng)功能的子程序,稱為系統(tǒng)調(diào)用。用戶可以通過(guò)系統(tǒng)調(diào)用命令在自己的應(yīng)用程序中調(diào)用它們。從某種角度來(lái)看,系
    發(fā)表于 08-23 10:37 ?741次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>中系統(tǒng)<b class='flag-5'>調(diào)用</b>詳解

    Linux內(nèi)核自解壓過(guò)程分析

    uboot完成系統(tǒng)引導(dǎo)以后,執(zhí)行環(huán)境變量bootm中的命令;即,將Linux內(nèi)核調(diào)入內(nèi)存中并調(diào)用do_bootm函數(shù)啟動(dòng)內(nèi)核,跳轉(zhuǎn)至kernel的起始位置。
    的頭像 發(fā)表于 12-08 14:00 ?799次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>自解壓<b class='flag-5'>過(guò)程</b>分析

    Linux內(nèi)核啟動(dòng)過(guò)程和Bootloader(總述)

    ,所以一般的 Bootloader 都會(huì)在執(zhí)行過(guò)程中初始化一個(gè)串口做為調(diào)試端口(3)檢測(cè)處理器類型 Bootloader在調(diào)用 Linux內(nèi)核前必須檢測(cè)系統(tǒng)的處理器類型,并將其保存到某
    發(fā)表于 08-18 17:35

    ARM linux系統(tǒng)調(diào)用的實(shí)現(xiàn)原理

    大家都知道linux的應(yīng)用程序要想訪問(wèn)內(nèi)核必須使用系統(tǒng)調(diào)用從而實(shí)現(xiàn)從usr模式轉(zhuǎn)到svc模式。下面咱們看看它的實(shí)現(xiàn)過(guò)程。
    發(fā)表于 05-30 11:24 ?2228次閱讀

    Linux內(nèi)核系統(tǒng)調(diào)用擴(kuò)展研究

    系統(tǒng)凋用是操作系統(tǒng)內(nèi)核提供給用戶使用內(nèi)核服務(wù)的接口。LinuX操作系統(tǒng)由于其自由開放性,用戶可在原有基礎(chǔ)上,添加新的系統(tǒng)調(diào)用,以便提供更多的服務(wù)。基于Linttx2.4
    發(fā)表于 07-25 16:09 ?40次下載
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>系統(tǒng)<b class='flag-5'>調(diào)用</b>擴(kuò)展研究

    編譯Linux2.6內(nèi)核并添加一個(gè)系統(tǒng)調(diào)用

    本文以實(shí)例來(lái)詳細(xì)描述了從準(zhǔn)備一直到使用新內(nèi)核Linux2.6 內(nèi)核編譯過(guò)程,然后介紹了添加系統(tǒng)調(diào)用的實(shí)現(xiàn)步驟,最后給實(shí)驗(yàn)結(jié)果。
    發(fā)表于 12-01 15:54 ?46次下載

    linux內(nèi)核啟動(dòng)內(nèi)核解壓過(guò)程分析

    linux啟動(dòng)時(shí)內(nèi)核解壓過(guò)程分析,一份不錯(cuò)的文檔,深入了解內(nèi)核必備
    發(fā)表于 03-09 13:39 ?1次下載

    嵌入式系統(tǒng)內(nèi)核引導(dǎo)啟動(dòng)過(guò)程淺析

    嵌入式系統(tǒng)內(nèi)核引導(dǎo)啟動(dòng)過(guò)程淺析
    發(fā)表于 10-30 10:26 ?6次下載
    嵌入式系統(tǒng)<b class='flag-5'>內(nèi)核</b>引導(dǎo)啟動(dòng)<b class='flag-5'>過(guò)程</b><b class='flag-5'>淺析</b>

    lattice DDR3 IP核的生成及調(diào)用過(guò)程

    本文以一個(gè)案例的形式來(lái)介紹lattice DDR3 IP核的生成及調(diào)用過(guò)程,同時(shí)介紹各個(gè)接口信號(hào)的功能作用
    發(fā)表于 03-16 14:14 ?2095次閱讀
    lattice DDR3 IP核的生成及<b class='flag-5'>調(diào)用過(guò)程</b>

    如何區(qū)分xenomai、linux系統(tǒng)調(diào)用/服務(wù)

    對(duì)于同一個(gè)POSIX接口應(yīng)用程序,可能既需要xenomai內(nèi)核提供服務(wù)(xenomai 系統(tǒng)調(diào)用),又需要調(diào)用linux內(nèi)核提供服務(wù)(
    的頭像 發(fā)表于 05-10 10:28 ?1968次閱讀

    Linux內(nèi)核系統(tǒng)調(diào)用概述及實(shí)現(xiàn)原理

    本文介紹了系統(tǒng)調(diào)用的一些實(shí)現(xiàn)細(xì)節(jié)。首先分析了系統(tǒng)調(diào)用的意義,它們與庫(kù)函數(shù)和應(yīng)用程序接口(API)有怎樣的關(guān)系。然后,我們考察了Linux內(nèi)核如何實(shí)現(xiàn)系統(tǒng)
    的頭像 發(fā)表于 05-14 14:11 ?2140次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>系統(tǒng)<b class='flag-5'>調(diào)用</b>概述及實(shí)現(xiàn)原理

    系統(tǒng)調(diào)用:用戶棧與內(nèi)核棧的切換(上)

    sysenter / sysexit 再到 syscall / sysret 實(shí)現(xiàn)方式的轉(zhuǎn)變,關(guān)于具體的演化和區(qū)別、系統(tǒng)調(diào)用的其他細(xì)節(jié)等將在以后的系統(tǒng)調(diào)用專欄里分析。本文從系統(tǒng)調(diào)用最原始的int 0x80開始分析用戶棧與
    的頭像 發(fā)表于 07-31 11:27 ?810次閱讀
    系統(tǒng)<b class='flag-5'>調(diào)用</b>:用戶棧與<b class='flag-5'>內(nèi)核</b>棧的切換(上)

    Linux系統(tǒng)調(diào)用的具體實(shí)現(xiàn)原理

    文我將基于 ARM 體系結(jié)構(gòu)角度,從 Linux 應(yīng)用層例子到內(nèi)核系統(tǒng)調(diào)用函數(shù)的整個(gè)過(guò)程來(lái)梳理一遍,講清楚linux系統(tǒng)
    的頭像 發(fā)表于 09-05 17:16 ?1038次閱讀
    <b class='flag-5'>Linux</b>系統(tǒng)<b class='flag-5'>調(diào)用</b>的具體實(shí)現(xiàn)原理