精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

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

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

分析unidbg(unidbgMutil)多線程機(jī)制

冬至子 ? 來源:看雪學(xué)苑 ? 作者:SilverBullet ? 2023-05-20 17:23 ? 次閱讀

一、概述

由于在工作中遇到了某翻譯so中有多線程調(diào)用,因此使用unidbg分析(基于unidbgMutilThread)并增加阻塞喚醒機(jī)制(futex系統(tǒng)調(diào)用),但仍未調(diào)用成功,因此本文概述對(duì)unidbg多線程的理解、android多線程的創(chuàng)建流程、實(shí)現(xiàn)簡單的阻塞喚醒、以及近段時(shí)間分析的總結(jié),也希望大神網(wǎng)友能提出寶貴意見及分析方向,文末會(huì)有相關(guān)內(nèi)容。

二、準(zhǔn)備

android6.0(sdk23) ,kernel源碼

相關(guān)源碼路徑:

/bionic/libc/bionic/pthread_create.cpp
/bionic/libc/bionic/pthread_mutex.cpp
/bionic/libc/bionic/pthread_cond.cpp


/bionic/libc/bionic/clone.cpp
/bionic/libc/arch-arm/bionic/__bionic_clone.S


/bionic/libc/private/bionic_futex.h
/kernel/kernel/futex.c

三、開始分析

1. unidbgMutil的多線程創(chuàng)建分析

我們知道,在C中創(chuàng)建一個(gè)線程是要用到pthread_create這個(gè)函數(shù)的,這個(gè)函數(shù)簡單來說,在用戶空間通過mmap為子線程分配線程棧空間,在底層的是使用了clone這個(gè)系統(tǒng)調(diào)用創(chuàng)建線程。

因此unidbgMutil也選擇在clone這個(gè)系統(tǒng)調(diào)用里面實(shí)現(xiàn)自己的線程創(chuàng)建。

//com.github.unidbg.linux.ARM32SyscallHandler 
private int pthread_clone(Backend backend, Emulator? emulator) {
        . . . . . .
        Pointer child_stack = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);


        Pointer fn = child_stack.getPointer(0);
        child_stack = child_stack.share(4);
        Pointer arg = child_stack.getPointer(0);
        child_stack = child_stack.share(4);


        threadId = ++ThreadDispatcher.thread_count_index;


        emulator.getThreadDispatcher().threadMap.put(threadId, new LinuxThread(emulator,child_stack, fn, arg));
        . . . . . .
}

這里可以看到,在clone的系統(tǒng)調(diào)用里,我們?nèi)〕隽薘1寄存器的值,然后又通過R1取得了fn、arg,接著創(chuàng)建一個(gè)LinuxThread對(duì)象,并把當(dāng)前線程id和這個(gè)對(duì)象綁定在一起,存入全局的threadMap中。然后在LinuxThread里保存當(dāng)前cpu上下文,保存線程棧,通過arg.getPointer(48) 獲取子線程函數(shù)的地址。通過this.arg.getPointer(52) 獲取子線程參數(shù)的地址。

圖片

其實(shí)到這里,我們需要分析一下,child_stack的連續(xù)取地址,arg的pointer 48,52的偏移究竟是什么,不然我們后續(xù)增加功能,修改代碼,就會(huì)一頭霧水。

2. Android 多線程分析

前邊簡單概述了pthread_create的相關(guān)內(nèi)容,但如果要了解unidbg的多線程實(shí)現(xiàn),我們則要詳細(xì)分析Android是如何創(chuàng)建多線程的。我們看代碼:

圖片

我們知道pthread_create一共有4個(gè)參數(shù),這里要關(guān)注第三和第四個(gè)參數(shù),也就是子線程函數(shù)的地址和參數(shù)。代碼塊1 調(diào)用了__allocate_thread函數(shù),傳入thread變量(pthread_internal_t結(jié)構(gòu)體,很重要),和child_stack指針。

圖片

進(jìn)入后我們發(fā)現(xiàn),這個(gè)函數(shù)的作用其實(shí)就是為我們的子線程,開啟一份棧空間,attr->guard_size是線程棧的保護(hù)區(qū)域這里是4k,__create_thread_mapped_space函數(shù)內(nèi)部通過mmap系統(tǒng)調(diào)用,分配出一份匿名、私有的空間供子線程使用。然后將分配的內(nèi)存大小,棧頂?shù)刂罚x值給threadp即pthread_internal_t。

圖片

到這里我們的棧空間已經(jīng)分配完成,接下來就要進(jìn)行子線程函數(shù)地址和參數(shù)的分配。也就是我們看到的在pthread_create代碼塊2那里,將start_routine和arg全都賦值給thread這個(gè)變量。然后就調(diào)用到clone這個(gè)函數(shù)。

clone:

int clone( int (*fn)(void *),
            void *child_stack,
            int flags,
            void *arg,
            .... /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );

通過查閱資料,linux中進(jìn)程和線程的創(chuàng)建在內(nèi)核中都是通過clone系統(tǒng)調(diào)用完成的,區(qū)別在于flags參數(shù),因?yàn)榫€程是可以共享進(jìn)程中的資源的,而進(jìn)程和進(jìn)程之間是隔離的,就是因?yàn)樵赾lone系統(tǒng)調(diào)用中,flags參數(shù)的作用,如CLONE_VM,CLONE_FS,CLONE_SIGHAND等。

也就是說線程創(chuàng)建的本質(zhì)是共享進(jìn)程的虛擬內(nèi)存、文件系統(tǒng)屬性、打開的文件列表、信號(hào)處理,以及將生成的線程加入父進(jìn)程所屬的線程組中等等。這里flags參數(shù)在pthread_create內(nèi)部已經(jīng)寫好,我們這里只需要關(guān)注fn,child_stack和arg就可以了。

fn 表示 clone 生成的子進(jìn)程/線程會(huì)調(diào)用 fn 指定的函數(shù),我們發(fā)現(xiàn)這里的fn,并不是pthread_create中傳進(jìn)來的子線程函數(shù)(start_routine),而是pthread_create內(nèi)部的函數(shù)__pthread_start,而這個(gè)函數(shù)的參數(shù)必然不可能是子線程函數(shù)的參數(shù),我們看一下,他的參數(shù)是thread變量(pthrea_internel_t),在我們前面的分析中,我們知道子線程的函數(shù)地址和函數(shù)參數(shù)就在這個(gè)thread變量中!

圖片

接著往下走,進(jìn)入clone函數(shù):

圖片

到這里,我們進(jìn)入了_bionic_clone這個(gè)函數(shù),這個(gè)函數(shù)在libc中是用匯編寫的,這里我們要注意下,_bionic_clone的參數(shù)和clone的參數(shù)位置,因?yàn)榻酉聛砦覀円治黾拇嫫骼锏膬?nèi)容,如果參數(shù)搞混了就頭疼了。這里我們記住,fn雖然是clone要調(diào)用的子線程函數(shù),但是我們真正的子線程函數(shù)在arg(thread)里。即fn -> __pthread_start,arg -> thread(子線程函數(shù),參數(shù)),child_stack是mmap分配的,不用多說。

圖片

進(jìn)入__bionic_clone這個(gè)匯編,他有7個(gè)參數(shù),我們知道arm函數(shù)調(diào)用的參數(shù)傳遞,少于4個(gè)參數(shù)由R0-R3完成,多于4個(gè)參數(shù)用棧(sp)傳遞,并且入棧的方式是從右向左入棧。

這個(gè)代碼以及注釋已經(jīng)寫得很清楚了,首先保存sp棧指針的值 mov ip, sp;然后將R4-R7入棧。linux的棧是高地址向低地址壓的,而且arm規(guī)定sp指向棧頂位置,因此下面兩條指令的含義是存儲(chǔ)原始的R4-R7寄存器的值,即將R4-R7入主線程的棧中,然后將ip中的值,也就是原始sp棧中的參數(shù)tid,fn,arg,加載到R4-R6寄存器中。

具體的stmfd,ldmfd,stmdb指令,可以查看相關(guān)資料,我畫了一個(gè)圖應(yīng)該更容易理解這幾條指令。

圖片

接下來的指令stmdb r1!, {r5, r6},很重要,這條指令是理解unidbg中對(duì)child_stack的指令偏移的關(guān)鍵。stmdb的含義是,地址先減然后完成操作,因此r1寄存器的地址先減4(減4是因?yàn)?2位)然后存入r6,再減4,存入r5。根據(jù)上邊的指令,r6里邊存的是arg參數(shù),r5里邊存放的是fn指針。

圖片

接下來的指令ldr r7, =__NR_clone;swi #0;則是通過R7傳遞系統(tǒng)調(diào)用號(hào),swi軟中斷(現(xiàn)在是svc指令,功能相同)從用戶空間(libc)真正進(jìn)入到內(nèi)核空間,之后的操作則是在內(nèi)核態(tài)由kernel操作(位置在/kernel/kernel/fork.c -> SYSCALL_DEFINE5 -> do_fork完成,這里不是我們的重點(diǎn)),在unidbg里則是直接進(jìn)入了ARM32SyscallHandler中的hook方法。

現(xiàn)在我們?cè)賮砜匆幌耤hild_stack的操作:

圖片

首先獲取R1寄存器的值(記得我們已經(jīng)在"內(nèi)核態(tài)"了),通過上邊的分析,我們已經(jīng)非常清楚了,此時(shí)R1里的值就是fn,這個(gè)fn就是__pthread_start,child_stack.share(4);相當(dāng)于R1地址加4,getPointer(0)就是獲取當(dāng)前地址里的值,即arg,還記得這個(gè)arg實(shí)際上是一個(gè)pthread_internel_t的結(jié)構(gòu)體,里面有我們子線程的函數(shù)地址和參數(shù)。

那么,this.fn = (UnidbgPointer) arg.getPointer(48);和UnidbgPointer this_arg=((UnidbgPointer) this.arg).getPointer(52);

猜想也能夠知道,就是pthread_internel_t的結(jié)構(gòu)體里的子線程函數(shù)和參數(shù),我們這里驗(yàn)證一下pthread_internel_t所占的內(nèi)存大小,由于類class(結(jié)構(gòu)體struct)中定義的成員函數(shù)和構(gòu)造和析構(gòu)函數(shù)不占整體的空間。

因此可以計(jì)算,next,prev,cleanup_stack(指針類型占4字節(jié)),tid(int類型占4字節(jié)),join_state(枚舉類型占4字節(jié)),即5 * 4 = 20個(gè)字節(jié)。

圖片

其中attr為結(jié)構(gòu)體,里面是int和指針類型,占4 * 6=24個(gè)字節(jié),不過按照我這里的計(jì)算方式為44個(gè)字節(jié)偏移,少了4個(gè)字節(jié),可能是計(jì)算join_state占用空間不對(duì),或者在哪塊有內(nèi)存對(duì)齊,有大神知道的話可以指導(dǎo)一下。

圖片

不過最終,start_routine所在的偏移是48個(gè)字節(jié)是沒毛病的,start_routine_arg所占的字節(jié)自然是48+4=52的位置。

到此,我們已經(jīng)完整的分析了unidbgMutil的多線程創(chuàng)建機(jī)制,接下來將實(shí)現(xiàn)阻塞喚醒功能,以及提出我遇到的問題。

四、問題

當(dāng)我在調(diào)用這個(gè)翻譯的so時(shí),配置好環(huán)境后,用unidbg調(diào)用,在單線程的時(shí)候,有些是可以成功的。調(diào)用這個(gè)so分兩步:

(1) 加載模型

(2) 翻譯

圖片

但問題是大部分要傳入翻譯的字段,在unidbg里會(huì)陷入一個(gè)死循環(huán),在系統(tǒng)調(diào)用號(hào)240的位置(futex),于是在大致看看so之后,發(fā)現(xiàn)這個(gè)so是使用多線程的,其中導(dǎo)入函數(shù)里面有很多關(guān)于線程同步的東西,鎖,信號(hào)量,條件變量等。于是我準(zhǔn)備在unidbg的基礎(chǔ)上實(shí)現(xiàn)同步機(jī)制。

1. 測(cè)試

首先寫了一個(gè)demo,例子很簡單,就是創(chuàng)建3個(gè)線程,在子線程里進(jìn)行加鎖,并用條件變量控制。主線程里是一個(gè)死循環(huán),只有子線程操作完畢后,主線程才會(huì)退出循環(huán),輸出完成的log。(測(cè)試用例的位置在unidbg-android/src/main/java/thread/Test )

圖片

圖片

圖片

2. 增加功能

在這個(gè)測(cè)試?yán)又校覀兪褂玫搅随i(pthread_mutex_lock),條件變量(pthread_cond_wait/signal)對(duì)線程進(jìn)行同步控制,而這些函數(shù)的底層機(jī)制都是使用到了futex這個(gè)系統(tǒng)調(diào)用,因此要了解一下linux futex機(jī)制。

(1) Futex概述

關(guān)于futex系統(tǒng)調(diào)用,網(wǎng)上資料很多,簡單來說,在android里可以實(shí)現(xiàn)進(jìn)程/線程間阻塞喚醒功能。他的參數(shù)有很多,最主要的是前三個(gè)參數(shù),第二個(gè)參數(shù)futex_op在android里只有兩個(gè)選項(xiàng),F(xiàn)UTEX_WAIT,F(xiàn)UTEX_WAKE即阻塞和喚醒。

int futex ( int *uaddr,  int futex_op,  int val,         
    const struct timespec *timeout,   /* or: uint32_t val2 */         
    int *uaddr2, int val3);

第一個(gè)參數(shù)uaddr是一個(gè)地址,地址里邊是一個(gè)int的值,一般被稱為futex字,或者futex變量。這個(gè)值一般是由用戶空間定義,比如pthread_mutex_lock函數(shù)在使用futex時(shí),futex字就是&mutex->state這個(gè)值。

他的作用是當(dāng)futex_op的類型為FUTEX_WAIT時(shí),會(huì)比較futex字和第三個(gè)參數(shù)val的大小,如果相同表示要進(jìn)入阻塞(不相等則失敗)。當(dāng)futex_op的類型為FUTEX_WAKE時(shí),第三個(gè)參數(shù)val的值,代表要喚醒阻塞著的進(jìn)程/線程數(shù),比如使用pthread_cond_broadcast時(shí),val為INT_MAX,即喚醒所有線程。

圖片

(2) unidbg futex修改

知道了futex的原理,我們自己實(shí)現(xiàn)阻塞喚醒也就有了思路,由于實(shí)現(xiàn)多線程的方式是基于指令的時(shí)間片。

圖片

因此,阻塞對(duì)于我們來講,也就是在一個(gè)線程被阻塞后,unidbg切換線程時(shí),不要切換到這個(gè)阻塞線程。喚醒就是可以重新切換到這個(gè)阻塞的線程。

因此我這里實(shí)現(xiàn)的方式比較簡單,在futex_wait里,將futex uaddr和當(dāng)前線程id關(guān)聯(lián)起來,然后將當(dāng)前線程id添加進(jìn)阻塞線程。

圖片

喚醒的方式,同樣簡單粗暴,移除阻塞在uaddr上的任意一個(gè)線程即可。

圖片

然后,每當(dāng)調(diào)用到futex阻塞和喚醒后,切換線程。

之前我切換線程時(shí),直接在futex里進(jìn)行切換,后來導(dǎo)致unicorn數(shù)據(jù)錯(cuò)亂,一直報(bào)Invalid memory read (UC_ERR_READ_UNMAPPED)錯(cuò)誤,這個(gè)錯(cuò)誤是unicorn在emu_start里,如果某條指令出現(xiàn)問題,則會(huì)拋出異常,但是并不會(huì)告訴你是哪條指令。

幸運(yùn)的是unidbg提供了tracecode的功能,于是經(jīng)過多次調(diào)試后最終發(fā)現(xiàn),在切換完線程進(jìn)行保存/恢復(fù)寄存器上下文后,R0寄存器的值總是為0,這個(gè)奇怪的現(xiàn)象聯(lián)想到,這正是futex的返回值。系統(tǒng)調(diào)用返回后,會(huì)修改R0寄存器的值,進(jìn)而導(dǎo)致了數(shù)據(jù)錯(cuò)亂。接著我們把切換線程的代碼放到系統(tǒng)調(diào)用返回之后就OK了。

圖片

然后,我們的阻塞喚醒已經(jīng)基本完成了(pthread_exit里有鎖會(huì)調(diào)用futex,會(huì)出現(xiàn)問題,不過線程已經(jīng)退出了這個(gè)問題就沒有再研究)。

五、總結(jié)

到這里,本文也快結(jié)束了,其實(shí)本文看似是個(gè)分析貼,實(shí)則是一個(gè)求助帖,因?yàn)樽詈笪胰匀粵]有把翻譯so調(diào)用成功。所以回過頭來,想了想近段時(shí)間一直在研究unidbg而減少了對(duì)翻譯so本身的研究,而對(duì)翻譯so的分析本身也充滿了挑戰(zhàn)。

所以請(qǐng)教各位網(wǎng)友,也想和大家交流一下,我們的目標(biāo)是用unidbg成功調(diào)用so,并不需要還原so的算法,如何更好的去分析多線程的so,然后用unidbg模擬出來,目前我的思路可能就是看出錯(cuò)堆棧,然后frida去hook原始so,比較跟unicorn調(diào)用的不同?

這個(gè)翻譯so在加載模型階段,會(huì)開啟4個(gè)線程,如果只單線程模式調(diào)用(只運(yùn)行主線程),模型的加載可以成功,但后續(xù)的翻譯階段有的會(huì)陷入死循環(huán)。使用多線程加載時(shí),加載模型階段失敗。希望有厲害的網(wǎng)友可以幫忙看一看。

最后,雖然沒有成功調(diào)用,但是對(duì)unidbg的理解又加深了一些,大致如下。

unidbg的內(nèi)存布局:

[0xffffffffL-0xffff0000L]svc #0  0xffff0fa0: bx lr


[0xffff0000L-0xfffe0000L]: ARMSvcMemory jni引用


[0xc0000000L-0xbff00000L] :  棧空間


[xxx - 0x40000000L] :  so起始地址
  • 打斷點(diǎn):emulator.attach().addBreakPoint(address);
  • 任意位置調(diào)試: emulator.attach().debug();
  • 任意位置打印調(diào)用棧:emulator.getUnwinder().unwind();
  • tracecode: emulator.traceCode(begin,end);
  • patchcode: emulator.getMemory().pointer(address).setInt(patchCode); // nop 0xbf00bf00;
  • 獲取modules:emulator.getMemory().getLoadedModules()。
  • 繼承IOResolver接口,在resolve函數(shù)里可以監(jiān)控open系統(tǒng)調(diào)用。
  • 實(shí)現(xiàn)VirtualModule子類,注冊(cè)register方法,可以實(shí)現(xiàn)"虛擬"so的加載。
  • 使用:

vm.setDvmClassFactory(newProxyClassFactory());ProxyDvmObject.createObject(vm,value);

通過反射可以直接使用java里的類。

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

    關(guān)注

    12

    文章

    3923

    瀏覽量

    127132
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5317

    瀏覽量

    120003
  • Linux系統(tǒng)
    +關(guān)注

    關(guān)注

    4

    文章

    591

    瀏覽量

    27353
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Java多線程的用法

    本文將介紹一下Java多線程的用法。 基礎(chǔ)介紹 什么是多線程 指的是在一個(gè)進(jìn)程中同時(shí)運(yùn)行多個(gè)線程,每個(gè)線程都可以獨(dú)立執(zhí)行不同的任務(wù)或操作。 與單線程
    的頭像 發(fā)表于 09-30 17:07 ?924次閱讀

    AT socket可以多線程調(diào)用嗎?

    請(qǐng)問AT socket 可以多線程調(diào)用嗎? 有互鎖機(jī)制嗎,還是要自己做互鎖。
    發(fā)表于 03-01 08:22

    Linux下多線程機(jī)制

    1 線程不能獨(dú)立運(yùn)行,要依附于進(jìn)程2 如果創(chuàng)建一個(gè)子線程只需要重新分配棧空間3 多個(gè)線程可以并行運(yùn)行4 線程之間可以有共同的全局變量(全局區(qū),任何
    發(fā)表于 11-11 09:53

    QNX環(huán)境下多線程編程

    介紹了QNX 實(shí)時(shí)操作系統(tǒng)和多線程編程技術(shù),包括線程間同步的方法、多線程程序的分析步驟、線程基本程序結(jié)構(gòu)以及實(shí)用編譯方法。QNX 是由加拿大
    發(fā)表于 08-12 17:37 ?30次下載

    LabWindows_CVI多線程技術(shù)的應(yīng)用研究

    分析線程與進(jìn)程的關(guān)系,研究了LabWindows/CVI多線程技術(shù)運(yùn)行機(jī)制及其數(shù)據(jù)保護(hù)機(jī)制,對(duì)利用異步定時(shí)器實(shí)現(xiàn)的
    發(fā)表于 08-29 14:53 ?68次下載
    LabWindows_CVI<b class='flag-5'>多線程</b>技術(shù)的應(yīng)用研究

    MFC下的多線程編程

    計(jì)算機(jī)上的上位機(jī)制作工具語言之MFC下的多線程編程
    發(fā)表于 09-01 14:55 ?0次下載

    MFC--多線程程序設(shè)計(jì)

    計(jì)算機(jī)上的上位機(jī)制作工具語言之MFC--多線程程序設(shè)計(jì)
    發(fā)表于 09-01 14:55 ?0次下載

    Windows多線程編程

    計(jì)算機(jī)上的上位機(jī)制作工具語言之Windows多線程編程,感興趣的可以看看。
    發(fā)表于 09-01 15:27 ?0次下載

    關(guān)于多線程編程教程及經(jīng)典應(yīng)用案例的匯總分析

    多處理機(jī)、多核心處理器以及芯片級(jí)多處理或同時(shí)多線程處理器。本文為大家介紹多線程在Linux環(huán)境下的編程及在實(shí)際環(huán)境中的應(yīng)用。 多線程技術(shù)在數(shù)據(jù)實(shí)時(shí)采集分析中的應(yīng)用 本文介紹的
    發(fā)表于 10-16 16:46 ?0次下載

    多線程好還是單線程好?單線程多線程的區(qū)別 優(yōu)缺點(diǎn)分析

    摘要:如今單線程多線程已經(jīng)得到普遍運(yùn)用,那么到底多線程好還是單線程好呢?單線程多線程的區(qū)別又
    發(fā)表于 12-08 09:33 ?8.1w次閱讀

    什么是多線程編程?多線程編程基礎(chǔ)知識(shí)

    摘要:多線程編程是現(xiàn)代軟件技術(shù)中很重要的一個(gè)環(huán)節(jié)。要弄懂多線程,這就要牽涉到多進(jìn)程。本文主要以多線程編程以及多線程編程相關(guān)知識(shí)而做出的一些結(jié)論。
    發(fā)表于 12-08 16:30 ?1.3w次閱讀

    linux多線程機(jī)制-線程同步

    1.引言  目前,許多流行的多任務(wù)操作系統(tǒng)都提供線程機(jī)制,線程就是程序中的 單個(gè)順序控制流。利用多線程進(jìn)行程序設(shè)計(jì),就是將一個(gè)程序(進(jìn)程)的任務(wù)劃分為執(zhí)行的多個(gè)部分(
    發(fā)表于 04-02 14:42 ?447次閱讀

    Python多線程的使用

    最近常常需要處理大量的crash數(shù)據(jù),對(duì)這些數(shù)據(jù)進(jìn)行分析,在此之前需要將存量的數(shù)據(jù)導(dǎo)入自己的數(shù)據(jù)庫,開始一天一天的去導(dǎo),發(fā)現(xiàn)太慢了,后來嘗試通過python多線程并行導(dǎo)入多天數(shù)據(jù),以此記錄對(duì)于Python多線程的使用。
    的頭像 發(fā)表于 03-17 14:57 ?1070次閱讀

    Linux中多線程編程的知識(shí)點(diǎn)

    Hello、Hello大家好,我是木榮,今天我們繼續(xù)來聊一聊Linux中多線程編程中的重要知識(shí)點(diǎn),詳細(xì)談?wù)?b class='flag-5'>多線程中同步和互斥機(jī)制
    發(fā)表于 04-26 17:27 ?585次閱讀
    Linux中<b class='flag-5'>多線程</b>編程的知識(shí)點(diǎn)

    多線程如何保證數(shù)據(jù)的同步

    。本文將詳細(xì)介紹多線程數(shù)據(jù)同步的概念、問題、以及常見的解決方案。 一、多線程數(shù)據(jù)同步概念 在多線程編程中,數(shù)據(jù)同步指的是通過某種機(jī)制來確保多個(gè)線程
    的頭像 發(fā)表于 11-17 14:22 ?1155次閱讀