国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

一文看懂 | fork 系統(tǒng)調(diào)用

共 10803字,需瀏覽 22分鐘

 ·

2021-10-22 01:54

前言

Unix標(biāo)準(zhǔn)的復(fù)制進(jìn)程的系統(tǒng)調(diào)用時(shí)fork(即分叉),但是Linux,BSD等操作系統(tǒng)并不止實(shí)現(xiàn)這一個(gè),確切的說linux實(shí)現(xiàn)了三個(gè),fork,vfork,clone(確切說vfork創(chuàng)造出來的是輕量級(jí)進(jìn)程,也叫線程,是共享資源的進(jìn)程)

系統(tǒng)調(diào)用描述
forkfork創(chuàng)造的子進(jìn)程是父進(jìn)程的完整副本,復(fù)制了父親進(jìn)程的資源,包括內(nèi)存的內(nèi)容task_struct內(nèi)容
vforkvfork創(chuàng)建的子進(jìn)程與父進(jìn)程共享數(shù)據(jù)段,而且由vfork()創(chuàng)建的子進(jìn)程將先于父進(jìn)程運(yùn)行
cloneLinux上創(chuàng)建線程一般使用的是pthread庫 實(shí)際上linux也給我們提供了創(chuàng)建線程的系統(tǒng)調(diào)用,就是clone

fork, vfork和clone的系統(tǒng)調(diào)用的入口地址分別是sys_fork, sys_vfork和sys_clone, 而他們的定義是依賴于體系結(jié)構(gòu)的, 因?yàn)樵谟脩艨臻g和內(nèi)核空間之間傳遞參數(shù)的方法因體系結(jié)構(gòu)而異

系統(tǒng)調(diào)用的參數(shù)傳遞

系統(tǒng)調(diào)用的實(shí)現(xiàn)與C庫不同, 普通C函數(shù)通過將參數(shù)的值壓入到進(jìn)程的棧中進(jìn)行參數(shù)的傳遞。由于系統(tǒng)調(diào)用是通過中斷進(jìn)程從用戶態(tài)到內(nèi)核態(tài)的一種特殊的函數(shù)調(diào)用,沒有用戶態(tài)或者內(nèi)核態(tài)的堆??梢员挥脕碓谡{(diào)用函數(shù)和被調(diào)函數(shù)之間進(jìn)行參數(shù)傳遞。系統(tǒng)調(diào)用通過CPU的寄存器來進(jìn)行參數(shù)傳遞。在進(jìn)行系統(tǒng)調(diào)用之前,系統(tǒng)調(diào)用的參數(shù)被寫入CPU的寄存器,而在實(shí)際調(diào)用系統(tǒng)服務(wù)例程之前,內(nèi)核將CPU寄存器的內(nèi)容拷貝到內(nèi)核堆棧中,實(shí)現(xiàn)參數(shù)的傳遞。

因此不同的體系結(jié)構(gòu)可能采用不同的方式或者不同的寄存器來傳遞參數(shù),而上面函數(shù)的任務(wù)就是從處理器的寄存器中提取用戶空間提供的信息, 并調(diào)用體系結(jié)構(gòu)無關(guān)的?_do_fork(或者早期的do_fork)函數(shù), 負(fù)責(zé)進(jìn)程的復(fù)制

即不同的體系結(jié)構(gòu)可能需要采用不同的方式或者寄存器來存儲(chǔ)函數(shù)調(diào)用的參數(shù), 因此linux在設(shè)計(jì)系統(tǒng)調(diào)用的時(shí)候, 將其劃分成體系結(jié)構(gòu)相關(guān)的層次和體系結(jié)構(gòu)無關(guān)的層次, 前者復(fù)雜提取出依賴與體系結(jié)構(gòu)的特定的參數(shù),后者則依據(jù)參數(shù)的設(shè)置執(zhí)行特定的真正操作。

fork, vfork, clone系統(tǒng)調(diào)用的實(shí)現(xiàn)

關(guān)于do_fork和_do_frok

linux2.5.32以后, 添加了TLS(Thread Local Storage)機(jī)制, clone的標(biāo)識(shí)CLONE_SETTLS接受一個(gè)參數(shù)來設(shè)置線程的本地存儲(chǔ)區(qū)。sys_clone也因此增加了一個(gè)int參數(shù)來傳入相應(yīng)的點(diǎn)tls_val。sys_clone通過do_fork來調(diào)用copy_process完成進(jìn)程的復(fù)制,它調(diào)用特定的copy_thread和copy_thread把相應(yīng)的系統(tǒng)調(diào)用參數(shù)從pt_regs寄存器列表中提取出來,但是會(huì)導(dǎo)致意外的情況。

only one code path into copy_thread can pass the CLONE_SETTLS flag, and that code path comes from sys_clone with its architecture-specific argument-passing order.

前面我們說了, 在實(shí)現(xiàn)函數(shù)調(diào)用的時(shí)候,我iosys_clone等將特定體系結(jié)構(gòu)的參數(shù)從寄存器中提取出來, 然后到達(dá)do_fork這步的時(shí)候已經(jīng)應(yīng)該是體系結(jié)構(gòu)無關(guān)了, 但是我們sys_clone需要設(shè)置的CLONE_SETTLS的tls仍然是個(gè)依賴與體系結(jié)構(gòu)的參數(shù), 這里就會(huì)出現(xiàn)問題。

因此linux-4.2之后選擇引入一個(gè)新的CONFIG_HAVE_COPY_THREAD_TLS,和一個(gè)新的COPY_THREAD_TLS接受TLS參數(shù)為 額外的長整型(系統(tǒng)調(diào)用參數(shù)大?。┑臓幷?。改變sys_clone的TLS參數(shù)unsigned long,并傳遞到copy_thread_tls。

/*?http://lxr.free-electrons.com/source/include/linux/sched.h?v=4.5#L2646??*/
extern?long?_do_fork(unsigned?long,?unsigned?long,?unsigned?long,?int?__user?*,?int?__user?*,?unsigned?long);
extern?long?do_fork(unsigned?long,?unsigned?long,?unsigned?long,?int?__user?*,?int?__user?*);


/*?linux2.5.32以后,?添加了TLS(Thread?Local?Storage)機(jī)制,?
?在最新的linux-4.2中添加了對(duì)CLONE_SETTLS?的支持?
????底層的_do_fork實(shí)現(xiàn)了對(duì)其的支持,?
????dansh*/

#ifndef?CONFIG_HAVE_COPY_THREAD_TLS
/*?For?compatibility?with?architectures?that?call?do_fork?directly?rather?than
?*?using?the?syscall?entry?points?below.?*/

long?do_fork(unsigned?long?clone_flags,
??????????????unsigned?long?stack_start,
??????????????unsigned?long?stack_size,
??????????????int?__user?*parent_tidptr,
??????????????int?__user?*child_tidptr)
{
????????return?_do_fork(clone_flags,?stack_start,?stack_size,
????????????????????????parent_tidptr,?child_tidptr,?0);
}
#endif

我們會(huì)發(fā)現(xiàn),新版本的系統(tǒng)中clone的TLS設(shè)置標(biāo)識(shí)會(huì)通過TLS參數(shù)傳遞, 因此_do_fork替代了老版本的do_fork。

老版本的do_fork只有在如下情況才會(huì)定義

  • 只有當(dāng)系統(tǒng)不支持通過TLS參數(shù)通過參數(shù)傳遞而是使用pt_regs寄存器列表傳遞時(shí)

  • 未定義CONFIG_HAVE_COPY_THREAD_TLS宏

參數(shù)描述
clone_flags與clone()參數(shù)flags相同, 用來控制進(jìn)程復(fù)制過的一些屬性信息, 描述你需要從父進(jìn)程繼承那些資源。該標(biāo)志位的4個(gè)字節(jié)分為兩部分。最低的一個(gè)字節(jié)為子進(jìn)程結(jié)束時(shí)發(fā)送給父進(jìn)程的信號(hào)代碼,通常為SIGCHLD;剩余的三個(gè)字節(jié)則是各種clone標(biāo)志的組合(本文所涉及的標(biāo)志含義詳見下表),也就是若干個(gè)標(biāo)志之間的或運(yùn)算。通過clone標(biāo)志可以有選擇的對(duì)父進(jìn)程的資源進(jìn)行復(fù)制;
stack_start與clone()參數(shù)stack_start相同, 子進(jìn)程用戶態(tài)堆棧的地址
regs是一個(gè)指向了寄存器集合的指針, 其中以原始形式, 保存了調(diào)用的參數(shù), 該參數(shù)使用的數(shù)據(jù)類型是特定體系結(jié)構(gòu)的struct pt_regs,其中按照系統(tǒng)調(diào)用執(zhí)行時(shí)寄存器在內(nèi)核棧上的存儲(chǔ)順序, 保存了所有的寄存器, 即指向內(nèi)核態(tài)堆棧通用寄存器值的指針,通用寄存器的值是在從用戶態(tài)切換到內(nèi)核態(tài)時(shí)被保存到內(nèi)核態(tài)堆棧中的(指向pt_regs結(jié)構(gòu)體的指針。當(dāng)系統(tǒng)發(fā)生系統(tǒng)調(diào)用,即用戶進(jìn)程從用戶態(tài)切換到內(nèi)核態(tài)時(shí),該結(jié)構(gòu)體保存通用寄存器中的值,并被存放于內(nèi)核態(tài)的堆棧中)
stack_size用戶狀態(tài)下棧的大小, 該參數(shù)通常是不必要的, 總被設(shè)置為0
parent_tidptr與clone的ptid參數(shù)相同, 父進(jìn)程在用戶態(tài)下pid的地址,該參數(shù)在CLONE_PARENT_SETTID標(biāo)志被設(shè)定時(shí)有意義
child_tidptr與clone的ctid參數(shù)相同, 子進(jìn)程在用戶太下pid的地址,該參數(shù)在CLONE_CHILD_SETTID標(biāo)志被設(shè)定時(shí)有意義

其中clone_flags如下表所示

CLONE_FLAGS

sys_fork的實(shí)現(xiàn)

不同體系結(jié)構(gòu)下的fork實(shí)現(xiàn)sys_fork主要是通過標(biāo)志集合區(qū)分, 在大多數(shù)體系結(jié)構(gòu)上, 典型的fork實(shí)現(xiàn)方式與如下

早期實(shí)現(xiàn)

架構(gòu)實(shí)現(xiàn)
armarch/arm/kernel/sys_arm.c, line 239
i386arch/i386/kernel/process.c, line 710
x86_64arch/x86_64/kernel/process.c, line 706
asmlinkage?long?sys_fork(struct?pt_regs?regs)
{
????return?do_fork(SIGCHLD,?regs.rsp,?®s,?0);
}

新版本

http://lxr.free-electrons.com/source/kernel/fork.c?v=4.5#L1785

#ifdef?__ARCH_WANT_SYS_FORK
SYSCALL_DEFINE0(fork)
{
#ifdef?CONFIG_MMU
????return?_do_fork(SIGCHLD,?0,?0,?NULL,?NULL,?0);
#else
????/*?can?not?support?in?nommu?mode?*/
????return?-EINVAL;
#endif
}
#endif

我們可以看到唯一使用的標(biāo)志是SIGCHLD。這意味著在子進(jìn)程終止后將發(fā)送信號(hào)SIGCHLD信號(hào)通知父進(jìn)程,

由于寫時(shí)復(fù)制(COW)技術(shù), 最初父子進(jìn)程的棧地址相同, 但是如果操作棧地址閉并寫入數(shù)據(jù), 則COW機(jī)制會(huì)為每個(gè)進(jìn)程分別創(chuàng)建一個(gè)新的棧副本

如果do_fork成功, 則新建進(jìn)程的pid作為系統(tǒng)調(diào)用的結(jié)果返回, 否則返回錯(cuò)誤碼

sys_vfork的實(shí)現(xiàn)

早期實(shí)現(xiàn)

架構(gòu)實(shí)現(xiàn)
armarch/arm/kernel/sys_arm.c, line 254
i386arch/i386/kernel/process.c, line 737
x86_64arch/x86_64/kernel/process.c, line 728
asmlinkage?long?sys_vfork(struct?pt_regs?regs)
{
????return?do_fork(CLONE_VFORK?|?CLONE_VM?|?SIGCHLD,?regs.rsp,?®s,?0);
}

新版本

http://lxr.free-electrons.com/source/kernel/fork.c?v=4.5#L1797

#ifdef?__ARCH_WANT_SYS_VFORK
SYSCALL_DEFINE0(vfork)
{
????return?_do_fork(CLONE_VFORK?|?CLONE_VM?|?SIGCHLD,?0,
????????????????????0,?NULL,?NULL,?0);
}
#endif

可以看到sys_vfork的實(shí)現(xiàn)與sys_fork只是略微不同, 前者使用了額外的標(biāo)志CLONE_VFORK | CLONE_VM

sys_clone的實(shí)現(xiàn)

早期實(shí)現(xiàn)

架構(gòu)實(shí)現(xiàn)
armarch/arm/kernel/sys_arm.c, line 247
i386arch/i386/kernel/process.c, line 715
x86_64arch/x86_64/kernel/process.c, line 711

sys_clone的實(shí)現(xiàn)方式與上述系統(tǒng)調(diào)用類似, 但實(shí)際差別在于do_fork如下調(diào)用

casmlinkage?int?sys_clone(struct?pt_regs?regs)
{
????/*?注釋中是i385下增加的代碼,?其他體系結(jié)構(gòu)無此定義
????unsigned?long?clone_flags;
????unsigned?long?newsp;

????clone_flags?=?regs.ebx;
????newsp?=?regs.ecx;*/

????if?(!newsp)
????????newsp?=?regs.esp;
????return?do_fork(clone_flags,?newsp,?®s,?0);
}

新版本

http://lxr.free-electrons.com/source/kernel/fork.c?v=4.5#L1805

#ifdef?__ARCH_WANT_SYS_CLONE
#ifdef?CONFIG_CLONE_BACKWARDS
SYSCALL_DEFINE5(clone,?unsigned?long,?clone_flags,?unsigned?long,?newsp,
?????????????????int?__user?*,?parent_tidptr,
?????????????????unsigned?long,?tls,
?????????????????int?__user?*,?child_tidptr)
#elif?defined(CONFIG_CLONE_BACKWARDS2)
SYSCALL_DEFINE5(clone,?unsigned?long,?newsp,?unsigned?long,?clone_flags,
?????????????????int?__user?*,?parent_tidptr,
?????????????????int?__user?*,?child_tidptr,
?????????????????unsigned?long,?tls)
#elif?defined(CONFIG_CLONE_BACKWARDS3)
SYSCALL_DEFINE6(clone,?unsigned?long,?clone_flags,?unsigned?long,?newsp,
????????????????int,?stack_size,
????????????????int?__user?*,?parent_tidptr,
????????????????int?__user?*,?child_tidptr,
????????????????unsigned?long,?tls)
#else
SYSCALL_DEFINE5(clone,?unsigned?long,?clone_flags,?unsigned?long,?newsp,
?????????????????int?__user?*,?parent_tidptr,
?????????????????int?__user?*,?child_tidptr,
?????????????????unsigned?long,?tls)
#endif
{
????????return?_do_fork(clone_flags,?newsp,?0,?parent_tidptr,?child_tidptr,?tls);
}
#endif

我們可以看到sys_clone的標(biāo)識(shí)不再是硬編碼的, 而是通過各個(gè)寄存器參數(shù)傳遞到系統(tǒng)調(diào)用, 因而我們需要提取這些參數(shù)。

另外,clone也不再復(fù)制進(jìn)程的棧, 而是可以指定新的棧地址, 在生成線程時(shí), 可能需要這樣做, 線程可能與父進(jìn)程共享地址空間, 但是線程自身的??赡茉诹硗庖粋€(gè)地址空間

另外還指令了用戶空間的兩個(gè)指針(parent_tidptr和child_tidptr), 用于與線程庫通信

創(chuàng)建子進(jìn)程的流程

_do_fork的流程

_do_fork和do_fork在進(jìn)程的復(fù)制的時(shí)候并沒有太大的區(qū)別, 他們就只是在進(jìn)程tls復(fù)制的過程中實(shí)現(xiàn)有細(xì)微差別

所有進(jìn)程復(fù)制(創(chuàng)建)的fork機(jī)制最終都調(diào)用了kernel/fork.c中的_do_fork(一個(gè)體系結(jié)構(gòu)無關(guān)的函數(shù)),

其定義在 http://lxr.free-electrons.com/source/kernel/fork.c?v=4.2#L1679

_do_fork以調(diào)用copy_process開始, 后者執(zhí)行生成新的進(jìn)程的實(shí)際工作, 并根據(jù)指定的標(biāo)志復(fù)制父進(jìn)程的數(shù)據(jù)。在子進(jìn)程生成后, 內(nèi)核必須執(zhí)行下列收尾操作:

  1. 調(diào)用 copy_process 為子進(jìn)程復(fù)制出一份進(jìn)程信息

  2. 如果是 vfork(設(shè)置了CLONE_VFORK和ptrace標(biāo)志)初始化完成處理信息

  3. 調(diào)用 wake_up_new_task 將子進(jìn)程加入調(diào)度器,為之分配 CPU

  4. 如果是 vfork,父進(jìn)程等待子進(jìn)程完成 exec 替換自己的地址空間

我們從<深入linux'內(nèi)核架構(gòu)>中找到了早期的流程圖,基本一致可以作為參考

do_fork
long?_do_fork(unsigned?long?clone_flags,
??????unsigned?long?stack_start,
??????unsigned?long?stack_size,
??????int?__user?*parent_tidptr,
??????int?__user?*child_tidptr,
??????unsigned?long?tls)
{
????struct?task_struct?*p;
????int?trace?=?0;
????long?nr;
??
????/*
?????*?Determine?whether?and?which?event?to?report?to?ptracer.??When
?????*?called?from?kernel_thread?or?CLONE_UNTRACED?is?explicitly
?????*?requested,?no?event?is?reported;?otherwise,?report?if?the?event
?????*?for?the?type?of?forking?is?enabled.
?????*/

????if?(!(clone_flags?&?CLONE_UNTRACED))?{
????if?(clone_flags?&?CLONE_VFORK)
????????trace?=?PTRACE_EVENT_VFORK;
????else?if?((clone_flags?&?CSIGNAL)?!=?SIGCHLD)
????????trace?=?PTRACE_EVENT_CLONE;
????else
????????trace?=?PTRACE_EVENT_FORK;
??
????if?(likely(!ptrace_event_enabled(current,?trace)))
????????trace?=?0;
????}
???/*??復(fù)制進(jìn)程描述符,copy_process()的返回值是一個(gè)?task_struct?指針??*/
????p?=?copy_process(clone_flags,?stack_start,?stack_size,
?????????child_tidptr,?NULL,?trace,?tls);
????/*
?????*?Do?this?prior?waking?up?the?new?thread?-?the?thread?pointer
?????*?might?get?invalid?after?that?point,?if?the?thread?exits?quickly.
?????*/

????if?(!IS_ERR(p))?{
????struct?completion?vfork;
????struct?pid?*pid;
??
????trace_sched_process_fork(current,?p);
???/*??得到新創(chuàng)建的進(jìn)程的pid信息??*/
????pid?=?get_task_pid(p,?PIDTYPE_PID);
????nr?=?pid_vnr(pid);
??
????if?(clone_flags?&?CLONE_PARENT_SETTID)
????????put_user(nr,?parent_tidptr);
???
????/*??如果調(diào)用的?vfork()方法,初始化?vfork?完成處理信息?*/
????if?(clone_flags?&?CLONE_VFORK)?{
????????p->vfork_done?=?&vfork;
????????init_completion(&vfork);
????????get_task_struct(p);
????}
?/*??將子進(jìn)程加入到調(diào)度器中,為其分配?CPU,準(zhǔn)備執(zhí)行??*/
????wake_up_new_task(p);
??
????/*?forking?complete?and?child?started?to?run,?tell?ptracer?*/
????if?(unlikely(trace))
????????ptrace_event_pid(trace,?pid);
???
????/*??如果是?vfork,將父進(jìn)程加入至等待隊(duì)列,等待子進(jìn)程完成??*/
????if?(clone_flags?&?CLONE_VFORK)?{
????????if?(!wait_for_vfork_done(p,?&vfork))
????????ptrace_event_pid(PTRACE_EVENT_VFORK_DONE,?pid);
????}
??
????put_pid(pid);
????}?else?{
????nr?=?PTR_ERR(p);
????}
????return?nr;
}

copy_process流程

http://lxr.free-electrons.com/source/kernel/fork.c?v=4.5#L1237

  1. 調(diào)用 dup_task_struct 復(fù)制當(dāng)前的 task_struct

  2. 檢查進(jìn)程數(shù)是否超過限制

  3. 初始化自旋鎖、掛起信號(hào)、CPU 定時(shí)器等

  4. 調(diào)用 sched_fork 初始化進(jìn)程數(shù)據(jù)結(jié)構(gòu),并把進(jìn)程狀態(tài)設(shè)置為 TASK_RUNNING

  5. 復(fù)制所有進(jìn)程信息,包括文件系統(tǒng)、信號(hào)處理函數(shù)、信號(hào)、內(nèi)存管理等

  6. 調(diào)用 copy_thread_tls 初始化子進(jìn)程內(nèi)核棧

  7. 為新進(jìn)程分配并設(shè)置新的 pid

我們從<深入linux'內(nèi)核架構(gòu)>中找到了早期的流程圖,基本一致可以作為參考

do_fork
/*
?*?This?creates?a?new?process?as?a?copy?of?the?old?one,
?*?but?does?not?actually?start?it?yet.
?*
?*?It?copies?the?registers,?and?all?the?appropriate
?*?parts?of?the?process?environment?(as?per?the?clone
?*?flags).?The?actual?kick-off?is?left?to?the?caller.
?*/

static?struct?task_struct?*copy_process(unsigned?long?clone_flags,
????????????????????unsigned?long?stack_start,
????????????????????unsigned?long?stack_size,
????????????????????int?__user?*child_tidptr,
????????????????????struct?pid?*pid,
????????????????????int?trace,
????????????????????unsigned?long?tls)
{
????int?retval;
????struct?task_struct?*p;

????retval?=?security_task_create(clone_flags);
????if?(retval)
????????goto?fork_out;
?//??復(fù)制當(dāng)前的?task_struct
????retval?=?-ENOMEM;
????p?=?dup_task_struct(current);
????if?(!p)
????????goto?fork_out;

????ftrace_graph_init_task(p);

????//初始化互斥變量
????rt_mutex_init_task(p);

#ifdef?CONFIG_PROVE_LOCKING
????DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
????DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
#endif

?//檢查進(jìn)程數(shù)是否超過限制,由操作系統(tǒng)定義
????retval?=?-EAGAIN;
????if?(atomic_read(&p->real_cred->user->processes)?>=
????????????task_rlimit(p,?RLIMIT_NPROC))?{
????????if?(p->real_cred->user?!=?INIT_USER?&&
????????????!capable(CAP_SYS_RESOURCE)?&&?!capable(CAP_SYS_ADMIN))
????????????goto?bad_fork_free;
????}
????current->flags?&=?~PF_NPROC_EXCEEDED;

????retval?=?copy_creds(p,?clone_flags);
????if?(retval?0)
????????goto?bad_fork_free;

????/*
?????*?If?multiple?threads?are?within?copy_process(),?then?this?check
?????*?triggers?too?late.?This?doesn't?hurt,?the?check?is?only?there
?????*?to?stop?root?fork?bombs.
?????*/

?//檢查進(jìn)程數(shù)是否超過?max_threads?由內(nèi)存大小決定
????retval?=?-EAGAIN;
????if?(nr_threads?>=?max_threads)
????????goto?bad_fork_cleanup_count;

????delayacct_tsk_init(p);??/*?Must?remain?after?dup_task_struct()?*/
????p->flags?&=?~(PF_SUPERPRIV?|?PF_WQ_WORKER);
????p->flags?|=?PF_FORKNOEXEC;
????INIT_LIST_HEAD(&p->children);
????INIT_LIST_HEAD(&p->sibling);
????rcu_copy_process(p);
????p->vfork_done?=?NULL;

????//??初始化自旋鎖
????spin_lock_init(&p->alloc_lock);
?//??初始化掛起信號(hào)
????init_sigpending(&p->pending);

????//??初始化?CPU?定時(shí)器
????posix_cpu_timers_init(p);
?//??......

????/*?Perform?scheduler?related?setup.?Assign?this?task?to?a?CPU.?
?????初始化進(jìn)程數(shù)據(jù)結(jié)構(gòu),并把進(jìn)程狀態(tài)設(shè)置為?TASK_RUNNING
????*/

????retval?=?sched_fork(clone_flags,?p);
????if?(retval)
????????goto?bad_fork_cleanup_policy;
?retval?=?perf_event_init_task(p);

????/*?復(fù)制所有進(jìn)程信息,包括文件系統(tǒng)、信號(hào)處理函數(shù)、信號(hào)、內(nèi)存管理等???*/
????if?(retval)
????????goto?bad_fork_cleanup_policy;
????retval?=?audit_alloc(p);
????if?(retval)
????????goto?bad_fork_cleanup_perf;
????/*?copy?all?the?process?information?*/
????shm_init_task(p);
????retval?=?copy_semundo(clone_flags,?p);
????if?(retval)
????????goto?bad_fork_cleanup_audit;
????retval?=?copy_files(clone_flags,?p);
????if?(retval)
????????goto?bad_fork_cleanup_semundo;
????retval?=?copy_fs(clone_flags,?p);
????if?(retval)
????????goto?bad_fork_cleanup_files;
????retval?=?copy_sighand(clone_flags,?p);
????if?(retval)
????????goto?bad_fork_cleanup_fs;
????retval?=?copy_signal(clone_flags,?p);
????if?(retval)
????????goto?bad_fork_cleanup_sighand;
????retval?=?copy_mm(clone_flags,?p);
????if?(retval)
????????goto?bad_fork_cleanup_signal;
????retval?=?copy_namespaces(clone_flags,?p);
????if?(retval)
????????goto?bad_fork_cleanup_mm;
????retval?=?copy_io(clone_flags,?p);
????if?(retval)
????????goto?bad_fork_cleanup_namespaces;
????/*????初始化子進(jìn)程內(nèi)核棧
?????linux-4.2新增處理TLS
????????之前版本是?retval?=?copy_thread(clone_flags,?stack_start,?stack_size,?p);
????????*/

????retval?=?copy_thread_tls(clone_flags,?stack_start,?stack_size,?p,?tls);
????if?(retval)
????????goto?bad_fork_cleanup_io;

?/*??為新進(jìn)程分配新的pid??*/
????if?(pid?!=?&init_struct_pid)?{
????????pid?=?alloc_pid(p->nsproxy->pid_ns_for_children);
????????if?(IS_ERR(pid))?{
????????????retval?=?PTR_ERR(pid);
????????????goto?bad_fork_cleanup_io;
????????}
????}

?/*??設(shè)置子進(jìn)程的pid??*/
????/*?ok,?now?we?should?be?set?up..?*/
????p->pid?=?pid_nr(pid);
????if?(clone_flags?&?CLONE_THREAD)?{
????????p->exit_signal?=?-1;
????????p->group_leader?=?current->group_leader;
????????p->tgid?=?current->tgid;
????}?else?{
????????if?(clone_flags?&?CLONE_PARENT)
????????????p->exit_signal?=?current->group_leader->exit_signal;
????????else
????????????p->exit_signal?=?(clone_flags?&?CSIGNAL);
????????p->group_leader?=?p;
????????p->tgid?=?p->pid;
????}

????p->nr_dirtied?=?0;
????p->nr_dirtied_pause?=?128?>>?(PAGE_SHIFT?-?10);
????p->dirty_paused_when?=?0;

????p->pdeath_signal?=?0;
????INIT_LIST_HEAD(&p->thread_group);
????p->task_works?=?NULL;

????/*
?????*?Make?it?visible?to?the?rest?of?the?system,?but?dont?wake?it?up?yet.
?????*?Need?tasklist?lock?for?parent?etc?handling!
?????*/

????write_lock_irq(&tasklist_lock);

?/*??調(diào)用fork的進(jìn)程為其父進(jìn)程??*/
????/*?CLONE_PARENT?re-uses?the?old?parent?*/
????if?(clone_flags?&?(CLONE_PARENT|CLONE_THREAD))?{
????????p->real_parent?=?current->real_parent;
????????p->parent_exec_id?=?current->parent_exec_id;
????}?else?{
????????p->real_parent?=?current;
????????p->parent_exec_id?=?current->self_exec_id;
????}

????spin_lock(¤t->sighand->siglock);

????//?......

????return?p;
}

dup_task_struct 流程

http://lxr.free-electrons.com/source/kernel/fork.c?v=4.5#L334

static?struct?task_struct?*dup_task_struct(struct?task_struct?*orig)
{
?struct?task_struct?*tsk;
?struct?thread_info?*ti;
?int?node?=?tsk_fork_get_node(orig);
?int?err;

?//分配一個(gè)?task_struct?節(jié)點(diǎn)
?tsk?=?alloc_task_struct_node(node);
?if?(!tsk)
??return?NULL;

?//分配一個(gè)?thread_info?節(jié)點(diǎn),包含進(jìn)程的內(nèi)核棧,ti?為棧底
?ti?=?alloc_thread_info_node(tsk,?node);
?if?(!ti)
??goto?free_tsk;

?//將棧底的值賦給新節(jié)點(diǎn)的棧
?tsk->stack?=?ti;

?//……

?return?tsk;

}
  1. 調(diào)用alloc_task_struct_node分配一個(gè) task_struct 節(jié)點(diǎn)

  2. 調(diào)用alloc_thread_info_node分配一個(gè) thread_info 節(jié)點(diǎn),其實(shí)是分配了一個(gè)thread_union聯(lián)合體,將棧底返回給 ti

union?thread_union?{
???struct?thread_info?thread_info;
??unsigned?long?stack[THREAD_SIZE/sizeof(long)];
};
  • 最后將棧底的值 ti 賦值給新節(jié)點(diǎn)的棧

  • 最終執(zhí)行完dup_task_struct之后,子進(jìn)程除了tsk->stack指針不同之外,全部都一樣!

sched_fork 流程

int?sched_fork(unsigned?long?clone_flags,?struct?task_struct?*p)
{
?unsigned?long?flags;
?int?cpu?=?get_cpu();

?__sched_fork(clone_flags,?p);

?//??將子進(jìn)程狀態(tài)設(shè)置為?TASK_RUNNING
?p->state?=?TASK_RUNNING;

?//??……

?//??為子進(jìn)程分配?CPU
?set_task_cpu(p,?cpu);

?put_cpu();
?return?0;
}

我們可以看到sched_fork大致完成了兩項(xiàng)重要工作,

  • 一是將子進(jìn)程狀態(tài)設(shè)置為 TASK_RUNNING,

  • 二是為其分配 CPU

copy_thread和copy_thread_tls流程

我們可以看到linux-4.2之后增加了copy_thread_tls函數(shù)和CONFIG_HAVE_COPY_THREAD_TLS宏

但是如果未定義CONFIG_HAVE_COPY_THREAD_TLS宏默認(rèn)則使用copy_thread同時(shí)將定義copy_thread_tls為copy_thread

#ifdef?CONFIG_HAVE_COPY_THREAD_TLS
extern?int?copy_thread_tls(unsigned?long,?unsigned?long,?unsigned?long,
????????????struct?task_struct?*,?unsigned?long)
;
#else
extern?int?copy_thread(unsigned?long,?unsigned?long,?unsigned?long,
????????????struct?task_struct?*)
;

/*?Architectures?that?haven't?opted?into?copy_thread_tls?get?the?tls?argument
?*?via?pt_regs,?so?ignore?the?tls?argument?passed?via?C.?*/

static?inline?int?copy_thread_tls(
????????unsigned?long?clone_flags,?unsigned?long?sp,?unsigned?long?arg,
????????struct?task_struct?*p,?unsigned?long?tls)
{
????return?copy_thread(clone_flags,?sp,?arg,?p);
}
#endif
內(nèi)核實(shí)現(xiàn)
4.5arch/x86/kernel/process_32.c, line 132
4.5arch/x86/kernel/process_64.c, line 155

下面我們來看32位架構(gòu)的copy_thread_tls函數(shù),他與原來的copy_thread變動(dòng)并不大, 只是多了后面TLS的設(shè)置信息

int?copy_thread_tls(unsigned?long?clone_flags,?unsigned?long?sp,
????unsigned?long?arg,?struct?task_struct?*p,?unsigned?long?tls)
{
????struct?pt_regs?*childregs?=?task_pt_regs(p);
????struct?task_struct?*tsk;
????int?err;
?/*??獲取寄存器的信息??*/
????p->thread.sp?=?(unsigned?long)?childregs;
????p->thread.sp0?=?(unsigned?long)?(childregs+1);
????memset(p->thread.ptrace_bps,?0,?sizeof(p->thread.ptrace_bps));

????if?(unlikely(p->flags?&?PF_KTHREAD))?{
????????/*?kernel?thread
?????????內(nèi)核線程的設(shè)置??*/

????????memset(childregs,?0,?sizeof(struct?pt_regs));
????????p->thread.ip?=?(unsigned?long)?ret_from_kernel_thread;
????????task_user_gs(p)?=?__KERNEL_STACK_CANARY;
????????childregs->ds?=?__USER_DS;
????????childregs->es?=?__USER_DS;
????????childregs->fs?=?__KERNEL_PERCPU;
????????childregs->bx?=?sp;?????/*?function?*/
????????childregs->bp?=?arg;
????????childregs->orig_ax?=?-1;
????????childregs->cs?=?__KERNEL_CS?|?get_kernel_rpl();
????????childregs->flags?=?X86_EFLAGS_IF?|?X86_EFLAGS_FIXED;
????????p->thread.io_bitmap_ptr?=?NULL;
????????return?0;
????}
????/*??將當(dāng)前寄存器信息復(fù)制給子進(jìn)程??*/
????*childregs?=?*current_pt_regs();
????/*??子進(jìn)程?eax?置?0,因此fork?在子進(jìn)程返回0??*/
????childregs->ax?=?0;
????if?(sp)
????????childregs->sp?=?sp;
?/*??子進(jìn)程ip?設(shè)置為ret_from_fork,因此子進(jìn)程從ret_from_fork開始執(zhí)行??*/
????p->thread.ip?=?(unsigned?long)?ret_from_fork;
????task_user_gs(p)?=?get_user_gs(current_pt_regs());

????p->thread.io_bitmap_ptr?=?NULL;
????tsk?=?current;
????err?=?-ENOMEM;

????if?(unlikely(test_tsk_thread_flag(tsk,?TIF_IO_BITMAP)))?{
????????p->thread.io_bitmap_ptr?=?kmemdup(tsk->thread.io_bitmap_ptr,
????????????????????????IO_BITMAP_BYTES,?GFP_KERNEL);
????????if?(!p->thread.io_bitmap_ptr)?{
????????????p->thread.io_bitmap_max?=?0;
????????????return?-ENOMEM;
????????}
????????set_tsk_thread_flag(p,?TIF_IO_BITMAP);
????}

????err?=?0;

????/*
?????*?Set?a?new?TLS?for?the?child?thread?
?????*?為進(jìn)程設(shè)置一個(gè)新的TLS
?????*/

????if?(clone_flags?&?CLONE_SETTLS)
????????err?=?do_set_thread_area(p,?-1,
????????????(struct?user_desc?__user?*)tls,?0);

????if?(err?&&?p->thread.io_bitmap_ptr)?{
????????kfree(p->thread.io_bitmap_ptr);
????????p->thread.io_bitmap_max?=?0;
????}
????return?err;
}

copy_thread 這段代碼為我們解釋了兩個(gè)相當(dāng)重要的問題!

  • 一是,為什么 fork 在子進(jìn)程中返回0,原因是childregs->ax = 0;這段代碼將子進(jìn)程的 eax 賦值為0
  • 二是,p->thread.ip = (unsigned long) ret_from_fork;將子進(jìn)程的 ip 設(shè)置為 ret_form_fork 的首地址,因此子進(jìn)程是從 ret_from_fork 開始執(zhí)行的

總結(jié)

fork, vfork和clone的系統(tǒng)調(diào)用的入口地址分別是sys_fork, sys_vfork和sys_clone, 而他們的定義是依賴于體系結(jié)構(gòu)的, 而他們最終都調(diào)用了_do_fork(linux-4.2之前的內(nèi)核中是do_fork),在_do_fork中通過copy_process復(fù)制進(jìn)程的信息,調(diào)用wake_up_new_task將子進(jìn)程加入調(diào)度器中

  1. dup_task_struct中為其分配了新的堆棧

  2. 調(diào)用了sched_fork,將其置為TASK_RUNNING

  3. copy_thread(_tls)中將父進(jìn)程的寄存器上下文復(fù)制給子進(jìn)程,保證了父子進(jìn)程的堆棧信息是一致的,

  4. 將ret_from_fork的地址設(shè)置為eip寄存器的值

  5. 為新進(jìn)程分配并設(shè)置新的pid

  6. 最終子進(jìn)程從ret_from_fork開始執(zhí)行

進(jìn)程的創(chuàng)建到執(zhí)行過程如下圖所示

進(jìn)程的狀態(tài)

轉(zhuǎn)自:

https://blog.csdn.net/gatieme/article/details/51569932

瀏覽 80
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)
評(píng)論
圖片
表情
推薦
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 国产精品乱码毛片在线人与| 中文字幕少妇| 国产A毛片| 国产欧美综合视频| 欧美日韩高清| 中文字幕av无码| 91露脸熟女四川熟女在线观看| 欧美老女人性爱视频| 欧美亚洲国产一区二区三区| 日本精品在线观看视频| 被男友内S~高H文| 午夜亚洲| 91成人亚洲| 一道本av| 日韩V| 真人BBwBBWBBw另类视频| 可以看的黄色视频| 啪啪成人视频| 欧美aaaaaa| 99热免费| 国产免费无码| aⅴ视频| 好吊视频一区二区| aa久久| 欧美日韩成人片| 国产精品av在线播放| 91视频免费| 国产精品久久77777| 996热久久| 亚洲美眉综合网| 中文字幕91| 成人做爰A片一区二区app | 99久久婷婷国产综合精品hsex | 三级A片视频| 亚洲精品无码一区| 日韩精品成人在线视频| 日韩aaa视频| 久久中文字幕免费| 亚洲秘AV无码一区二区qq群| 成人性生活视频| 内射精品| 激情五月综合网| 蜜臀一区二区三区| 岛国免费av| 国产理论电影在线观看| 亚洲第一免费视频| 特级毛片WWW| 天天添| 欧美sesese| 精品中文字幕在线| 国产乱伦AV网站| 久久久久亚洲AV无码网影音先锋 | 69性爱视频| 国产视频123区| 国产又粗又长又硬又大毛苴茸图片 | 一区二区三区www污污污网站| 亚洲综合二区| 五月天婷婷在线视频| 日本黄色视频。| 北岛玲视频在线| 国产一级二级三级视频| 六月婷婷在线观看| 国产一级免费在线观看| 欧美婷婷五月| 日韩欧美国产黄色电影| 内射学生妹J亅| 韩国精品一区| 超碰C| 亚洲无吗在线播放| 六月天av| 手机看片福利视频| 91精品国产一区| 韩国三级无码| 91国产人妻| 北条麻妃精品视频| 免费无码婬片AAAAA片| 日本一区二区三区四区在线观看| 欧美日韩一级黄色片| 嫩草久久| 苍井空视频| 日韩成人无码电影网站| 久久亚洲AV成人无码国产野外| 九一成人网| 97伊人大香蕉| 国产高清第一页| 成人在线激情| 久久天天拍| 影音先锋成人在线资源| 亚洲.无码.制服.日韩.中文字幕 | 亚洲第一狼人综合网| 综合站欧美精品| 黑人干亚洲人| 日韩无码人妻系列| 热热热热色| 西西人体444www| 日韩欧美性爱视频| 韩国无码视频在线观看| 国产一区一区| 一区二区三区四区五区| 少妇婷婷| 无码人妻精品一区| 中日韩免费视频| 欧美黑人操逼| 成人黄色一级片| 一本道高清无码视频| 国产一级无码| 日韩A级片| 看国产AA免费| 午夜成人福利视频| 国产一级在线免费观看| 欧美国产另类| 免费一区视频| 激情久久AV一区AV二区AV三区| 水果派解说av| A片免费观看视频| 欧美丰满美乳XXⅩ高潮www | 国产精品久久久久久婷婷天堂 | 久久6热| 午夜福利sw| 好看的中文字幕av| 日韩精品毛片| 乱伦激情| 国产精品成人免费久久黄AV片| 亚洲日韩欧美视频| 97超碰在| 中文字幕乱妇无码Av在线| 大香蕉啪啪啪| 欧美性爱天天| 欧美性一区| 国产视频精品一区二区三区| 天堂在线9| 国产嫩苞又嫩又紧AV在线| 一级黄色毛片视频| 国产又爽又黄免费视频免费| 91视频久久| 五月天激情小说| 中国乱伦视频| 免费的黄色片| 亚洲无码在线观看网站| 午夜福利视频网站| 成年人视频在线免费观看| 日韩在线观看一区| 日韩精品人妻中文字幕蜜乳| 熟女导航| 欧美精品xxx| 日韩精品一区二区三区在线观看免费| 苍井空无码在线观看| 大吊AV| jjzz国产| 无码一区二区三区在线| 中文字幕无码在线| 无码三级AV| 亚洲免费观看高清完整| 可以免费观看的毛片| 免费观看AV| 亚洲日韩视频在线| 河南少妇搡BBBB搡BBBB| 久久婷婷五月天| av国产精品| AV在线资源观看| 亚洲一级二级三级片| 色婷婷成人| 一区亚洲| 国产群交| 91丨PORNY丨在线中文| 黄色大片网址| 特黄AAAAAAAA片免费直播| 黄色AV免费在线观看| 亚洲成人性爱网| 欧美操| 偷窥丶亚洲丶熟女| 国产精品一区av| 中文字幕在线中文| 亚洲国产三级片| 亚洲成人视频网站| 中文字幕在线观看1| igao在线观看| 99热综合在线| 北条麻妃99| 美女一级片| 在线免费小黄片| 国产精品午夜在线| 俺去也在线视频| 天天看天天日| 亚洲黄色AV| 日韩一级中文字幕| 免费一级AAAAA片在线播放| 又黄又爽无遮挡| 欧美性猛交XXXX乱大交3| 精品黄片| 最新中文字幕无码| 国产日韩一区二区三区| 久操视频在线免费观看| 欧美亚洲天堂| 女女女女女女BBBBBB手| 亚洲三级电影在线观看| 色秘乱码一区二区三区唱戏| 日韩AV无码电影| 最美孕交vivoestv另类| 无码欧精品亚洲日韩一区| 97中文字幕在线| 亚洲精品97久久中文字幕| 亚洲欧美不卡| 中文电视剧字幕在线播放免费视频| 欧美午夜福利在线观看| 激情亚洲| 日本黄色大片网站| 色情一级AA片免费观看| 老司机无码视频| 东京热久久综合色五月老师 | 日本午夜视频| 无码在线视频免费观看| 色中色AV| 黄色一级免费看| 无码三级在线观看| 俺来俺去www色婷婷| 欧美日在线观看| 色色色热热热| www.狠狠操| 影音先锋女人资源| 国产香蕉在线视频| 国产黄色在线播放| 九七色色电影| 操逼123首页| 99热这里精品| 久久久久久久国产| 影音先锋色色| 偷拍精品视频| 日韩高清不卡| 亚洲国产成人精品午夜| 91干干| www中文字幕| 三洞齐开Av在线免费观看| 看A片在线| 五月天AV在线| 日逼无码| 青娱乐国产精品一区二区| 大香蕉AV在线观看| 亚洲精品资源| 中字无码AV| 亚洲在线中文| 蜜臀99久久精品久久久久久软件 | 免费观看亚洲视频| h片在线看| 日本熟女视频| 黄色视频在线观看| 一区二区三区四区高清无码| 久久99精品国产| 男人的天堂色琪琪| 91在线无码精品秘国产-百度| 中文字幕免费在线| 天天干夜夜操| 日韩中文无| 激情五月综合| 中文字幕无码免费| 人妻天天干| 成人看片33x9.CC| 中文字幕性爱电影| 美女黄色免费网站| 国产性爱网站| 天堂中文在线播放| 无码少妇视频| 在线观看视频日韩| aaaaaa在线观看免费高清| 一区在线播放| 亚洲精品久久久久毛片A级牛奶| 性生活无码| 中文字幕不卡+婷婷五月| 爽爽午国产浪潮AV性色www| 欧美日韩成人在线观看| 欧美九九九| 天天日天天噜| 国产香蕉在线观看| 大香蕉在线免| 黄在观看线| 成人性爱网站| 国产日韩欧美久久| 探花AV| 无码东京热国产| 波多野结衣国产区42部| 日韩高清一区二区| 亚洲日韩一区二区三区四区| 大地资源38页| 西西444WWW大胆无| 国语一区| 永久免费视频| 91人妻一区二区三区无不码超满| 久久草在线播放| 麻豆成人91精品二区三区| 日韩1区2区| 琪琪色视频| 69视频在线免费观看| 国产黄色视屏| www.91av| 日韩三级在线播放| 九哥操逼视频| 欧美精品在线免费观看| 国产一级A片久久久免费看快餐| 性视频人人| 成人精品秘免费波多野结衣| 久久系列| 久久久久亚洲精品| 亚洲天天| 狠狠操夜夜操| AV色色| 翔田千里无码流出两部| 日本成人高清视频| www.久久久久| 人人肏肏人人| 丝袜一区二区三区| 看毛片网站| 四房五月婷婷| 日韩美女视频19| www.毛片| AV三级片在线观看| 囯产一级黄片| AV网站免费看| 国产精品免费麻豆| 国产视频一区二区三区四区五区 | 国产福利精品视频| 国产无码久久久| 俺也去也| 欧美一道本在线| 久操视频在线观看免费| 亚洲高清国产欧美综合s8| 河南熟妇搡BBBB搡BBBB| 欧美一级A片高清免费播放| 国产免费av网站| 日韩三级在线| 日本成人一区二区| 青青草无码成人天堂免费| 国产精品自在线| 久久嫩草精品久久久久| 高清毛片AAAAAAAAA郊外| 在线观看视频91| 未满十八18禁止免费无码网站 | a在线观看| 天天综合在线观看| 精品免费视频| 日韩性生活网| 在线播放中文字幕| 12—13女人毛片毛片| 久热中文字幕| 亚洲色婷婷五月天| 大香蕉99| 91精品成人| 驲韩在线视频免费观看| 欧美在线无码| 丝瓜视频污APP| 亚洲女人视频| 蜜桃影视| 最新国产视频| 日本少妇bbw| 久久久久免费| 国产精品精品| 久久女人视频| 国产精品人人人人| 91在线无码精品秘入口| 欧洲综合视频| 五月婷婷丁香五月| aaa三级黄片| 18禁网址| 国产成人精品麻豆| 国产精品乱码毛片在线人与| 一级黄色毛片视频| 国产51视频| 人妻二区| 无码在线播放观看| 91久久综合亚洲鲁鲁五月天| 人人操人人妻人人爽| 国产第一页在线观看| 成人AV在线资源| 一区二区三区在线看| 亚洲成人性爱视频| 91性爱小视频| 影音先锋成人片| 欧美aⅤ| jk无码| 久操免费在线观看| 欧美性网| 国产不卡一| 阿宾MD0165麻豆沈娜娜| www.日韩无码| 欧美aⅤ| 天堂成人网| 91大神网址| 操逼免费观看| 福利视频一区二区| 欧美亚洲黄色| 神马午夜精品| 久9久9久9久9久9久9| 久色| 噜噜噜在线视频| 日韩欧美在线中文| 偷拍亚洲| 五月丁香婷婷在线观看| 久久青| 国产欧美日韩在线视频| 无码成人视频| 欧美日韩在线视频播放| a片免费网址| 无码电影网站| 午夜天堂精品久久久久9| 韩国日本美国免费毛片| 成人精品无码免费视频| 久草网在线观看| 超碰日韩| 51妺嘿嘿午夜福利在线| 91麻豆精品国产91久久久久久久久 | 久久精品国产AV| 青青草青娱乐| 久久香蕉网站| 国产精品久久久久久久免牛肉蒲| 一级欧美一级日韩片| 中文字幕在线观看网| 久久久999| 亚洲区中文字幕| 丰满少妇一级片| 打炮影院| 性欧美欧美巨大69| 逼逼75大秀| 亚洲无码成人视频| 欧美日韩肏屄视频| 99成人| 天天操天天操天天| www.色中色| 熟女无码| 日韩av中文字幕在线| 中国老少配BBwBBwBBW| 欧美、日韩、中文、制服、人妻| 亚洲AV综合网| 久久午夜无码鲁丝午夜精品| 免费A视频| 色天堂在线观看视频| 在线看操逼| 国产成人精品三级麻豆| 18精品爽国产冫绿帽社| 综合成人在线| www.色五月| 高清无码在线免费观看视频| 久久国产热在8| 欧美老逼| 国产乱伦毛片| 日本一区二区三区四区| 国产白丝在线| 日韩AV成人电影| 亚洲精品久久久久毛片A级牛奶| 麻豆乱码国产一区二区三区| 成人精品一区二区区别解析| 色婷婷Av一区| 日韩福利视频| 爱爱视频h| 久久b| 国产高清AV| 日本熟妇一区二区三区| 国产av天天| 天堂网视频| 五月婷婷深深爱| 五月婷在线观看| 久久成人久久| 欧美日韩国产精品| 北条麻妃在线一区| 97精品超碰一区二区三区| 日韩性爱视频| 国产成人无码免费看片| 97精品人妻一区二区三区香蕉| 一起操逼| 无码专区一区二区三区| 中国一级黄色毛片| 91就去干| 巨い巨乳の少妇あジed2k| 国产在线观看av| 天堂av在线免费观看| 日本成人免费电影| 欧美一区二区在线| 婷婷五月天综合| 九色PORNY丨自拍蝌蚪| 18禁网站网址| 91免费网站| 91人妻人人澡人人澡人人精品| 亚洲日本三级| 日本无码久久嗯啊流水| 国产黄色精品| 特级西西444www大精品| 91日韩高清| 青青草无码在线视频| 日韩在线电影| 日韩天堂网| 97播播| 激情av天堂| 在线你懂| 丁香五月五月婷婷| 亚洲午夜成人精品一区二区| 亚洲乱码一区| 久久免费精品视频| 日本无码免费视频| www.日逼| 性欧美丰满熟妇XXXX性久久久| 91在线视频播放| 国产成人亚洲综合A∨婷婷| 黄色视频在线免费观看网站| 2017天天射| 日韩一级黄片| 国产又粗又长的视频| 国产视频不卡| 亚洲第一成年人网站| 国产在线久久久| 884aa四虎影成人精品一区| 精品1区| 一区二区三区电影网| 欧美va视频| 日韩人妻精品无码久久边| 国产黄色网页| 91视频免费播放| 亚洲一卡二卡三卡四卡免| 国产一级黄色毛片| 躁BBB躁BBB躁BBBBBB| 嘿嘿午夜| 亚洲国产日本| 亚洲成人无码视频在线观看| 夜夜夜夜骑| 日韩一级片| 婷婷伊人綜合中文字幕| 欧美第五页| 亚洲色图1| 成人精品二区| 91大神在线免费看| 一级免费黄色电影| 人妻少妇无码精品| 亚洲无码精品一区| 黄色一级大片在线免费看国产| 婷婷天天干| 无码少妇| 18禁一区二区三区| 午夜网页| 夜夜撸天天干| 亚洲AV无码乱码国产精品| 精品国产一二三| 91成人视频| 热久久久| 人妻丰满熟妇av无码区| 日韩一级片免费看| 国产成人主播| 日本在线视频不卡| 少妇456| 国产日韩欧美在线观看| 2021无码| 天天干人妻| 91久久成人| 日日操人人操| 特级西西444www| yy午夜福利| 亚洲综合伊人| 成人免费无码| 黄色影片在线观看| 久久在线精品| 乱子伦国产精品视频一级毛 | 色老板视频在线观看| 日韩在线第—页| 日韩综合区| 久久午夜无码鲁丝午夜精品| 91大长腿美女花外围在线观看| 伊人亚洲| 91探花视频精选在线播放| 91香蕉国产在线观看软件| 激情视频免费在线观看| 日韩AV中文字幕在线播放| 人人操人人上| 人人爽爽人人| 国产精品国内自产拍| 麻豆久久| 亚洲热在线| 91成人免费电影| 亚洲制服在线观看| 一区二区黄| 欧美啊啊啊| 九色PORNY丨自拍蝌蚪| 超碰av电影| 99AV| 新狠狠干| 亚洲天堂无码a| 五月久久| 色婷婷综合久久久中文字幕| 黄a网站| 亚洲无码成人在线观看| 安微妇搡BBBB搡BBBB| 91久久人澡人妻人人做人人爽97| 超碰青青青| 96精品| 婷婷视频导航| 成人午夜A片免费看| 天天操嫩逼无套视频| 波多野结衣AV在线| 中国女人操逼视频| 五月天激情电影| 一区二区视频在线观看| 日韩午夜福利| 91足浴店按摩漂亮少妇| 日韩乱伦av| 男女操逼视频网站| 亚洲天堂无码AV| 1000部毛片A片免费视频| 天堂国产一区二区三区| 中文字幕五月天| 国产精品无码成人AV电影| 国产乱码精品一区二区三区的特点 | 午夜福利无码电影| 天堂网影音先锋| 日日碰狠狠躁久久躁婷婷| 污污污污污www网站免费民国| 国产人妻一区二区三区欧美毛片| 国产精品视频在线观看| 成人在线视频免费观看| 超碰免费在线观看| 91玖玖| www.插插插| 日本黄网站| 亚洲无码专区在线| 北条麻妃网址| 精品区| 成人做爰100部免费网站| 欧美黄片免费在线观看| 无套内射学生妹去看片| 这里只有精品在线观看| a片视频网站| 日本高清视频免费观看| 久久精品视频9| 亚洲精品免费在线观看| 日韩无码少妇| 在线免费观看a| 成人婷婷五月天| 日韩在线观看av| 免费看的操逼视频| 一区二区三级片| 99久久国产精| 日本黄色影院在线| 99久热在线精品| 婷婷六月色| 53岁露大奶熟女偷情贴吧| 丁香五月婷婷基地| sm国产在线调教视频| 久久久久黄片| AV天堂中文字幕| BBw日本熟妇BBwHD| 国产精品扒开腿做爽爽爽视频 | AⅤ中文字幕在线免费观看| 超碰在线| 东方美美高清无码一区| 欧洲黑种人日P视频| 亚洲精品一区二区二区的游戏情况| 亚洲无码门| 婷婷色777777| 亚洲国产精品自在自线| 国产一级a毛一级a做免费的视频l 精品国产免费观看久久久_久久天天 | 大香蕉中文视频| 操老骚逼视频| 国产又爽又黄免费观看| 撸一撸av| 91久久精品日日躁夜夜躁欧美 | 九九久久精品视频| 美女扣逼网站| 日韩一级性爱视频| 中文字幕va| 午夜AV福利| 黄色免费观看网站| 国产成人性爱| 亚洲午夜在线观看| 欧美亚洲日韩中文字幕| 日韩va中文字幕无码免费| 成人黄片视频| 国产精品美女毛片真酒店| 影音先锋成人资源站| 91成人亚洲| 天天操天天日天天干| 中文字幕在线免费看| 婷婷情色五月| 苍井空无码一区二区三区| 蝌蚪窝视频网| 日本三级片中文字幕| AV高清无码在线观看| 久久超碰99| 国产视频a| 欧美区亚洲区| 麻豆影音先锋| 91精品丝袜久久久久久久久粉嫩| 国产综合久久久7777777| 久草久| 日韩黄色一级视频| 在线观看黄色视频网站| 九色PORNY国产成人蝌蚪| 国产无套在线观看| 亚洲AAAAAA| 久久精品视频播放| 国产精品嫩草久久久久yw193| 大香蕉偷拍视频| 日本黄色视频网| 99热国产在线观看| 人妻av中文字幕| 黄骗免费网站| 五月天最新网址| 在线观看中文字幕av| 成人一级精品| 成人精品A片免费网站| 天天射天天干天天| 翔田千里无码一区| 一区二区在线免费观看| 五月天色色网站| 久久免费视频播放| 波多野结衣视频在线| 波多野结衣av无码| 色情欧美一级A片| 五月天久久久久久| 一本色道久久88亚洲精品综合| 91理伦| 真人BBwBBWBBw另类视频| 久久国产精品一区二区三区| 亚洲日韩欧美视频| 一二三四在线视频| 亚洲综合色网| 淫色人妻网| 国产高清在线免费观看AV片| 亚洲Av无码午夜国产精品色软件| 国产中文字幕第一页| av无码一区二区| 操比网| BBW老熟女BBw| 久热超碰| 久久99高清视频| 亚洲网站在线免费观看| 精品精品精品| ThePorn-成人网站入口| 色五月中文字幕| 欧美成人精品一区二区三区 | www.黄色大片| 欧美不卡一区二区| 在线免费观看无码视频| www.激情五月天| 日韩精品人妻中文字幕蜜乳| 国产黄色大片| 天天日夜夜撸| 欧美成人日韩| 欧美亚洲成人电影| 国产91精品探花一区二区| 无码中文字幕网站| 激情无码视频| 亚洲中文字幕日韩在线| 手机看片1024你懂的| 青青操成人在线视频| 欧美一区二区在线视频| AAA免费视频| 激情99| 久久成人在线视频| 久久久久久久艹| 日韩AV成人电影| 丁香五月影院| 亚洲av免费| 国产精品久久久一区二区三区 | 日本人妻中文字幕| 亚洲AV秘一区二区色盗战流出| 国产女人水真多18毛片18精品 | 江苏妇搡BBB搡BBBB| 亚洲自拍电影| 99爱视频| 国产精品欧美综合亚洲| 免费看黄色毛片| 日韩综合在线视频| 天天看天天日| 日韩18禁| 日韩av中文字幕在线播放| 成人自拍视频在线| 老熟女导航| 夜夜草视频| 99热9| 日韩无码黄色电影| 亚洲男人的天堂av| 精品久久成人| 成人精品在线视频| 色婷婷激情五月天| 青青久久91| 日韩人妻精品中文字幕专区不卡| 69视频国产| 亚洲精品秘一区二区三区蜜桃久 | 亚洲一线在线观看| 天堂视频在线观看亚洲美女 | 欧美XXXXBBBB| 中文字幕av一区| 91麻豆精品国产91久久久吃药| 四虎精品影院| 麻豆成人片| 扒开让我91看片在线看| 自拍偷拍15p| 高清无码在线观看18| 狼友视频报放| 国产一区二区不卡视频| 日本欧美在线视频| 日韩AV高清| 色青娱乐| 久久久精品一区| 欧美精品系列| 偷拍一区二区| 麻豆91免费视频| 免费黄视频在线观看| 男女啊啊啊| a国产| 日本中出视频| 欧美成人性爱在线| 国产人人色| 97精品国产| 999热这里只有精品| 无码在线免费播放| 亚洲无码精品在线观看| 波多野结衣一区二区| 天天射网站| 麻豆精品一区二区| 啪啪网站免费| 亚洲天堂av在线观看| 骚逼日本| 97黄片| 亚洲一级二级三级| 国产精品久久免费视频| 国产黄色小视频在线观看| 欧美性爱-熊猫成人网| 日本处女性高潮喷水视频| 色色色五月婷婷| 特级西西444www大精品| 成人网站在线免费看| 国产女主播在线播放| 国产精品宾馆在线| 免费网站观看www在线观看| 国产免费黄色视频| 8050午夜一级| 一级一A片一a免费看| www.日韩精品| 四川BBB搡BBB爽爽爽欧美| 曰曰摸日日碰| av无码网站| 操欧美女人| 天干天干天夜夜| 欧美日韩99| 成人性爱福利视频| 亚洲淫秽视频| 黄a在线观看| AⅤ中文字幕在线免费观看| 18禁看网站| 免费看成人A片无码照片88hⅤ| 亚洲AV电影在线观看| 91天天在线| 又黄又爽无遮挡| 成人在线免费观看视频| 91香蕉视频在线看| 中文字幕熟女| 无码第一页| 91香蕉视频在线看| 国产传媒_色哟哟| 国产熟妇| 欧美色图视频在线观看| 欧美国产日韩在线观看| 亚洲精品影院| 中文字幕在线播放av| 操屄网| 91爱搞搞| 99久久网站| 国产免费AV网站| 褒姒AV无玛| 国产麻豆传媒| 三级久久久| 亚洲高清人妻| 亚洲砖区区免费| 2021无码| 一级黄A片| 亚l洲视频在线观看| 国产视频久久久| 性性性性性XXXXX| av网站免费看| 娇小,学生,高潮,videos| 久久久123| 日本A级毛片| 一级毛AA片| 91精品91久久久中77777| 天天看片天天爽| 肏逼网站| 97婷婷五月天| 黄片免费在线播放| 日本三级片网站在线观看| 午夜福利视频3000| 91无码电影| 精品国产AV鲁一鲁一区| AAA久久| 伊人黄色| 国产精品九九九九九九| 黄色日逼片| 婷婷五月大香蕉| 午夜啪啪视频| 最近中文字幕免费MV第一季歌词十| 黑人精品XXX一区一二区| 99人人操| 日韩精品一区二区三区四区| 成人做爰黄A片免费看| 天天视频黄| 麻豆黄色电影|