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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

usleep的--系统调用流程--及不准确的问题 - Android4 0 1

發(fā)布時(shí)間:2024/3/24 Android 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 usleep的--系统调用流程--及不准确的问题 - Android4 0 1 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

首先給大家分享一個(gè)巨牛巨牛的人工智能教程,是我無(wú)意中發(fā)現(xiàn)的。教程不僅零基礎(chǔ),通俗易懂,而且非常風(fēng)趣幽默,還時(shí)不時(shí)有內(nèi)涵段子,像看小說(shuō)一樣,哈哈~我正在學(xué)習(xí)中,覺(jué)得太牛了,所以分享給大家!點(diǎn)這里可以跳轉(zhuǎn)到教程

1.由于在不同的硬件平臺(tái)上經(jīng)常遇到usleep不準(zhǔn)確的問(wèn)題,比如usleep(2*1000),結(jié)果sleep了10ms,是不是有點(diǎn)過(guò)分,測(cè)試代碼如下:

#include <stdio.h>#include <stdlib.h>int main(int argc,char **argv){??? struct timeval oldTime, newTime;??? int iStime,i,j;??? iStime=5;??? for(i=0;i<60;i++)??? {??????? for(j=0;j<10;j++)??????? {??????????? gettimeofday( &oldTime, NULL );??????????? usleep( iStime * 1000 );??????????? gettimeofday( &newTime, NULL );??????????? printf("iStime:%d,actual time:%lld\n",iStime,((long long)(newTime.tv_sec*1000 + newTime.tv_usec/1000)-(long long)(oldTime.tv_sec*1000 + oldTime.tv_usec/1000)));??????? }??????? iStime++;??? }}

當(dāng)然為防止出現(xiàn)意外,禁止測(cè)試期間設(shè)置系統(tǒng)時(shí)間。

?

2. 根據(jù)以前的經(jīng)驗(yàn),此usleep不準(zhǔn)主要是由于Kernel中系統(tǒng)timer的rating值過(guò)高引起的。

?

3. 下面從源碼的角度分析一下usleep的實(shí)現(xiàn)細(xì)節(jié),并進(jìn)一步分析其原因。以下以Android4.0.1為例進(jìn)行分析。注此問(wèn)題主要與Kernel有關(guān),與glibc或bionic無(wú)關(guān),因?yàn)樾〉茏罱鉇ndroid,所以就以Android為例進(jìn)行研究。

?

4. 首先找到usleep的源碼:

//位于/bionic/libc/unistd/usleep.c#include <time.h>#include <errno.h>int usleep(unsigned long usec){? struct timespec ts;? ts.tv_sec? = usec/1000000UL;#ifdef __arm__??? /* avoid divisions and modulos on the ARM */? ts.tv_nsec = (usec - ts.tv_sec*1000000UL)*1000;#else? ts.tv_nsec = (usec % 1000000UL) * 1000UL;#endif? for (;;)? {??? if ( nanosleep( &ts, &ts ) == 0 )??????? return 0;??? // We try again if the nanosleep failure is EINTR.??? // The other possible failures are EINVAL (which we should pass through),??? // and ENOSYS, which doesn't happen.??? if ( errno != EINTR )??????? return -1;? }}


它也很懶的,就調(diào)用了nanosleep,哪就看看nanasleep的源碼吧! 不幸是只找到一個(gè)extern int? nanosleep(const struct timespec *, struct timespec *); 它位于/bionic/libc/include/sys/linux-unistd.h,并沒(méi)有找到它的實(shí)現(xiàn)。其實(shí)看看Linux系統(tǒng)調(diào)用,早就知道它是一個(gè)系統(tǒng)調(diào)用,哪就分析一下是如何進(jìn)行系統(tǒng)調(diào)用的,以前只是講過(guò)原理,并沒(méi)有實(shí)例,在此把它完成了。

?

5. 尋找系統(tǒng)調(diào)用函數(shù)

如果這個(gè)函數(shù)沒(méi)有實(shí)現(xiàn),哪肯定是不能調(diào)用的,就像MIT教授在公開(kāi)課上所講的,搞計(jì)算機(jī)的不像搞別的,做不了假,別人不管你怎么設(shè)計(jì)的,只看你實(shí)現(xiàn)的結(jié)果,很有道理。也證明了搞if else的人不能做弊。哪就從它的Android.mk入手吧,看看還Link了什么東東。打開(kāi)libc的Android.mk發(fā)現(xiàn),其中有一行

include $(LOCAL_PATH)/arch-$(TARGET_ARCH)/syscalls.mk

這就是關(guān)鍵所在,syscalls系統(tǒng)調(diào)用,不正是我們要找的嗎?進(jìn)入arch-arm/syscalls.mk一看,其中一大片.s,Search一下,看有沒(méi)有nanosleep.s,還真有這么一行,真是大快人心:syscall_src += arch-arm/syscalls/nanosleep.S

趕緊去瞧瞧,ARM匯編水平不高,能看懂嗎?先把代碼貼上再說(shuō),不懂就問(wèn)google.

/* autogenerated by gensyscalls.py */#include <sys/linux-syscalls.h>??? .text??? .type nanosleep, #function??? .globl nanosleep??? .align 4??? .fnstartnanosleep:??? .save?? {r4, r7}??? stmfd?? sp!, {r4, r7}??? ldr???? r7, =__NR_nanosleep??? swi???? #0??? ldmfd?? sp!, {r4, r7}??? movs??? r0, r0??? bxpl??? lr??? b?????? __set_syscall_errno??? .fnend

__NR_nanosleep是個(gè)什么東東,憑直覺(jué),肯定在sys/linux-syscalls.h中有定義。打開(kāi)/libc/include/sys/linux-syscalls.h并search __NR_nanosleep, 明白了,它定義了__NR_nanosleep的值為(__NR_SYSCALL_BASE + 162),其實(shí)就是定義了其系統(tǒng)調(diào)用號(hào)。這就與前一文swi連接起來(lái)了。上面的代碼把系統(tǒng)調(diào)用號(hào)傳遞給r7,然后觸發(fā)了一個(gè)軟中斷,從而進(jìn)入內(nèi)核態(tài)執(zhí)行。

?

6. 軟中斷處理流程

根據(jù)常識(shí),既然是軟中斷,就一定有一個(gè)對(duì)應(yīng)的ISR,打開(kāi)/kernel/arch/arm/kernel/entry-common.S,發(fā)現(xiàn)其中有一個(gè)ENTRY(vector_swi),這就是我們要找的ISR,其詳細(xì)代碼如下:

.align 5ENTRY(vector_swi) sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12}?? @ Calling r0 - r12 ARM( add r8, sp, #S_PC? ) ARM( stmdb r8, {sp, lr}^? ) @ Calling sp, lr THUMB( mov r8, sp?? ) THUMB( store_user_sp_lr r8, r10, S_SP ) @ calling sp, lr mrs r8, spsr?? @ called from non-FIQ mode, so ok. str lr, [sp, #S_PC]?? @ Save calling PC str r8, [sp, #S_PSR]? @ Save CPSR str r0, [sp, #S_OLD_R0]? @ Save OLD_R0 zero_fp /*? * Get the system call number.? */#if defined(CONFIG_OABI_COMPAT) /*? * If we have CONFIG_OABI_COMPAT then we need to look at the swi? * value to determine if it is an EABI or an old ABI call.? */#ifdef CONFIG_ARM_THUMB tst r8, #PSR_T_BIT movne r10, #0??? @ no thumb OABI emulation ldreq r10, [lr, #-4]?? @ get SWI instruction#else ldr r10, [lr, #-4]?? @ get SWI instruction? A710( and ip, r10, #0x0f000000? @ check for SWI? )? A710( teq ip, #0x0f000000????? )? A710( bne .Larm710bug????? )#endif#ifdef CONFIG_CPU_ENDIAN_BE8 rev r10, r10?? @ little endian instruction#endif#elif defined(CONFIG_AEABI) /*? * Pure EABI user space always put syscall number into scno (r7).? */? A710( ldr ip, [lr, #-4]?? @ get SWI instruction )? A710( and ip, ip, #0x0f000000? @ check for SWI? )? A710( teq ip, #0x0f000000????? )? A710( bne .Larm710bug????? )#elif defined(CONFIG_ARM_THUMB) /* Legacy ABI only, possibly thumb mode. */ tst r8, #PSR_T_BIT?? @ this is SPSR from save_user_regs addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in ldreq scno, [lr, #-4]#else /* Legacy ABI only. */ ldr scno, [lr, #-4]?? @ get SWI instruction? A710( and ip, scno, #0x0f000000? @ check for SWI? )? A710( teq ip, #0x0f000000????? )? A710( bne .Larm710bug????? )#endif#ifdef CONFIG_ALIGNMENT_TRAP ldr ip, __cr_alignment ldr ip, [ip] mcr p15, 0, ip, c1, c0? @ update control register#endif enable_irq get_thread_info tsk adr tbl, sys_call_table? @ load syscall table pointer ldr ip, [tsk, #TI_FLAGS]? @ check for syscall tracing#if defined(CONFIG_OABI_COMPAT) /*? * If the swi argument is zero, this is an EABI call and we do nothing.? *? * If this is an old ABI call, get the syscall number into scno and? * get the old ABI syscall table address.? */ bics r10, r10, #0xff000000 eorne scno, r10, #__NR_OABI_SYSCALL_BASE ldrne tbl, =sys_oabi_call_table#elif !defined(CONFIG_AEABI) bic scno, scno, #0xff000000? @ mask off SWI op-code eor scno, scno, #__NR_SYSCALL_BASE @ check OS number#endif stmdb sp!, {r4, r5}?? @ push fifth and sixth args tst ip, #_TIF_SYSCALL_TRACE? @ are we tracing syscalls? bne __sys_trace cmp scno, #NR_syscalls? @ check upper syscall limit adr lr, BSYM(ret_fast_syscall) @ return address ldrcc pc, [tbl, scno, lsl #2]? @ call sys_* routine add r1, sp, #S_OFF2: mov why, #0??? @ no longer a real syscall cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE) eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back bcs arm_syscall? b sys_ni_syscall?? @ not private funcENDPROC(vector_swi)


7. 找與nanosleep對(duì)應(yīng)的處理函數(shù)

從上面的代碼中可以看出,它將調(diào)用sys_call_table中的某個(gè)函數(shù)。在同一個(gè)文件中尋找sys_call_table,其代碼如下:

.type sys_call_table, #objectENTRY(sys_call_table)#include "calls.S"


看看linux/arch/arm/kernel/calls.S中的內(nèi)容:

/* 0 */? CALL(sys_restart_syscall)? CALL(sys_exit)? CALL(sys_fork_wrapper)? CALL(sys_read)? CALL(sys_write)??????????????? .../* 160 */ CALL(sys_sched_get_priority_min)? CALL(sys_sched_rr_get_interval)? CALL(sys_nanosleep)? CALL(sys_mremap)? CALL(sys_setresuid16)


原來(lái)nanosleep系統(tǒng)調(diào)用在Kernel中的函數(shù)為sys_nanosleep,現(xiàn)在去分析一下是如何實(shí)現(xiàn)高精度的sleep的,是忙等(執(zhí)行nop指令),還是閑等(讓出CPU使用權(quán))呢? 馬上就會(huì)有答案了。由于小弟知識(shí)有限,沒(méi)哪么簡(jiǎn)單,我找了2個(gè)小時(shí)也沒(méi)有找到答案,慚愧啊!

?

8. 先看看熟悉的系統(tǒng)調(diào)用open吧!

也不幸運(yùn),沒(méi)有sys_open這樣的函數(shù)。反正知道這個(gè)東東在fs/open.c中,基本原理應(yīng)該是一樣的。在此文件中找到了下面這個(gè)函數(shù):

SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)

?

linux/syscalls.h定義如下:

asmlinkage long sys_open(const char __user *filename,int flags, int mode); (asmlinkage就是一個(gè)extern "C")

?

這兄弟倆長(zhǎng)得太像了,再看看SYSCALL_DEFINE3的定義,看看能不能找到二者的關(guān)系。

哈哈哈哈哈哈.....,終于在linux/syscalls.h中找到答案了,SYSCALL_DEFINE3的定義如下:

#define __SYSCALL_DEFINEx(x, name, ...) asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))#define SYSCALL_DEFINEx(x, sname, ...) __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)


把SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)還原就變成了:

asmlinkage long sys_open(const char __user *filename,int flags, int mode);是不是與要找的函數(shù)一模一樣呢?終于找到如何看這個(gè)代碼的方法了!

?

9. 繼續(xù)找sys_nanosleep的實(shí)現(xiàn)代碼

先看看linux/kernel/hrtimer.c中的commnets:

?*? High-resolution kernel timers
?*
?*? In contrast to the low-resolution timeout API implemented in
?*? kernel/timer.c, hrtimers provide finer resolution and accuracy
?*? depending on system configuration and capabilities.
?*
?*? These timers are currently used for:
?*?? - itimers
?*?? - POSIX timers
?*?? - nanosleep
?*?? - precise in-kernel timing

看到上面的nanosleep了嗎?說(shuō)明有機(jī)會(huì)找到了。

SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,??struct timespec __user *, rmtp)這不就是我要找的嗎? 由于這是一個(gè)宏,在SourceInsight中查找函數(shù)nanosleep是找不到的,search字符串nanosleep是可行的。其代碼如下:

SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,? struct timespec __user *, rmtp){ struct timespec tu; if (copy_from_user(&tu, rqtp, sizeof(tu)))? return -EFAULT; if (!timespec_valid(&tu))? return -EINVAL; return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);}


hrtimer_nanosleep實(shí)現(xiàn)如下:

long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,???????? const enum hrtimer_mode mode, const clockid_t clockid){ struct restart_block *restart; struct hrtimer_sleeper t; int ret = 0; unsigned long slack; slack = current->timer_slack_ns; if (rt_task(current))? slack = 0; hrtimer_init_on_stack(&t.timer, clockid, mode); hrtimer_set_expires_range_ns(&t.timer, timespec_to_ktime(*rqtp), slack); if (do_nanosleep(&t, mode))? goto out; /* Absolute timers do not update the rmtp value and restart: */ if (mode == HRTIMER_MODE_ABS) {? ret = -ERESTARTNOHAND;? goto out; } if (rmtp) {? ret = update_rmtp(&t.timer, rmtp);? if (ret <= 0)?? goto out; } restart = ¤t_thread_info()->restart_block; restart->fn = hrtimer_nanosleep_restart; restart->nanosleep.index = t.timer.base->index; restart->nanosleep.rmtp = rmtp; restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer); ret = -ERESTART_RESTARTBLOCK;out: destroy_hrtimer_on_stack(&t.timer); return ret;}static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode){ hrtimer_init_sleeper(t, current); do {? set_current_state(TASK_INTERRUPTIBLE);? hrtimer_start_expires(&t->timer, mode);? if (!hrtimer_active(&t->timer))?? t->task = NULL;? if (likely(t->task))?? schedule();? hrtimer_cancel(&t->timer);? mode = HRTIMER_MODE_ABS; } while (t->task && !signal_pending(current)); __set_current_state(TASK_RUNNING); return t->task == NULL;}



調(diào)用流程如下:

nanosleep()--> sys_nanosleep()--> hrtimer_nanosleep()--> do_nanosleep()--> hrtimer_start()--> enqueue_hrtimer() -->hrtimer_enqueue_reprogram()--> hrtimer_reprogram()-->int tick_program_event(ktime_t expires, int force)->
? (struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; 獲得clock_event_device)

int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires, int force)->

int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,ktime_t now) ->

dev->set_next_event((unsigned long) clc, dev)<在注冊(cè)的clock_event_device中提供此函數(shù),其主要功能是設(shè)置相關(guān)寄存器,以設(shè)置此超時(shí)事件>

?

?

?

?

?

?

?

?

?

???????????

瀏覽人工智能教程

總結(jié)

以上是生活随笔為你收集整理的usleep的--系统调用流程--及不准确的问题 - Android4 0 1的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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

主站蜘蛛池模板: 亚洲熟女乱综合一区二区三区 | 一二三四av| 色国产精品 | 综合欧美亚洲 | 久久久久不卡 | 在线免费播放av | 91中文字幕在线观看 | 台湾无码一区二区 | 激情欧美一区二区三区 | 亚洲国产综合av | 国产一二三区在线视频 | 日韩av网址在线观看 | 99精品欧美 | 中文字幕一区二区三区久久久 | 五月婷婷久久综合 | 成人a级网站 | 国产一级片中文字幕 | 欧美视频导航 | 免费在线播放黄色片 | 色偷偷888欧美精品久久久 | 粗口调教gay2022.com | 日韩无码精品一区二区三区 | 福利姬在线观看 | 激情综合文学 | 色吧五月天 | www.成人av.com| 亚洲色成人www永久网站 | www.av免费 | 亚洲成av人片一区二区梦乃 | www.白虎 | 综合久色 | www天堂网| 亚洲天堂视频在线观看 | 免费在线观看污网站 | 在线免费不卡视频 | 日韩逼 | 五月激情站 | 欧美日韩国产麻豆 | 国产成人免费片在线观看 | 特一级黄色大片 | 91网站免费在线观看 | 精品国产视频在线 | 国产这里只有精品 | 日本十大三级艳星 | 久久亚洲影视 | 操日本老太太 | 男人的天堂中文字幕 | 亚洲av无一区二区三区久久 | 69re视频| 国产91国语对白在线 | 欧美做受69 | 亚洲最大福利视频网 | 欧美一卡二卡三卡 | 亚洲第九页 | 在线天堂在线 | 亚洲欧美一区二区三区在线 | 亚洲欧洲综合在线 | 日本999视频| 高清av一区二区 | 2024av视频| 日本激情视频在线观看 | 欧美高清性 | 黄色男女网站 | 一区二区免费在线视频 | 日韩a级片| 性猛交xxxx乱大交孕妇印度 | 男人和女人日b视频 | 在线观看麻豆视频 | 日本黄色片免费看 | 欧美成人激情在线 | 亚洲欧洲日韩综合 | 一级久久久久久久 | 亚洲伊人精品 | 91亚洲视频在线观看 | 色综合av综合无码综合网站 | 亚洲情趣 | 免费人成又黄又爽又色 | 国产精品久久久久久亚洲 | 欧美激情一区二区三区蜜桃视频 | www日韩欧美 | 最新中文字幕免费视频 | 精品久久久久亚洲 | 免费一级a毛片夜夜看 | 国产情侣一区二区 | 成人视频在线观看 | 男插女av | 香蕉视频在线观看网站 | 日韩欧美一级 | 欧美成人黑人猛交 | 日本成人午夜 | 美女诱惑一区二区 | 一区二区高清在线观看 | 免费看一级黄色大片 | 超级碰在线观看 | 精品理论片| 国产精品久久久久久久久久久免费看 | 艳妇臀荡乳欲伦交换电影 | 国产女主播喷水视频在线观看 | 天堂福利在线 |