php thread linux,Linux_linux内核函数kernel_thread,设备驱动程序中,如果需要几 - phpStudy...
linux內(nèi)核函數(shù)kernel_thread
設(shè)備驅(qū)動(dòng)程序中,如果需要幾個(gè)并發(fā)執(zhí)行的人物,可以啟動(dòng)內(nèi)核線程,啟動(dòng)內(nèi)和縣城的函數(shù)為:
int kernel_thread (int ( * fn )( void * ), void * arg, unsigned long flags);
kernel_thread函數(shù)的作用是產(chǎn)生一個(gè)新的線程
內(nèi)核線程實(shí)際上就是一個(gè)共享父進(jìn)程地址空間的進(jìn)程,它有自己的系統(tǒng)堆棧.
內(nèi)核線程和進(jìn)程都是通過(guò)do_fork()函數(shù)來(lái)產(chǎn)生的,系統(tǒng)中規(guī)定的最大進(jìn)程數(shù)與
線程數(shù)由fork_init來(lái)決定:
[/arch/kernel/process.c/fork_init()]
void __init fork_init(unsigned long mempages)
{
#ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
#ifndef ARCH_MIN_TASKALIGN
#define ARCH_MIN_TASKALIGN?? L1_CACHE_BYTES
#endif
/* 在slab高速緩存中建立task_struct結(jié)構(gòu)專用的緩沖區(qū)隊(duì)列 */
task_struct_cachep =
kmem_cache_create("task_struct", sizeof(struct task_struct),
ARCH_MIN_TASKALIGN, SLAB_PANIC, NULL, NULL);
#endif
/*
把默認(rèn)線程數(shù)設(shè)置到一個(gè)安全值,因?yàn)閮?nèi)核中總的線程占用的空間
可能要內(nèi)存一半還要多.
參數(shù)mempages系統(tǒng)中總的物理內(nèi)存結(jié)構(gòu)大小,它等于mempages/PAGESIZE.
比如我機(jī)器的內(nèi)存是512m,那么在我的系統(tǒng)最多能同時(shí)產(chǎn)生線程數(shù)為
(512*2^20/2^12) / 2^3 = 512*2^5 = 16384
*/
max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE);
/*
* 啟動(dòng)系統(tǒng)的時(shí)候至少需要20個(gè)線程
*/
if(max_threads < 20)
max_threads = 20;
/*
* 每個(gè)進(jìn)程最多產(chǎn)生max_threads/2,也就是線程總數(shù)的一半,在我的機(jī)器上為8192.
*/
init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
}
kernel_thread原形在/arch/kernel/process.c中.
(*fn)(void *)為要執(zhí)行的函數(shù)的指針,arg為函數(shù)參數(shù),flags為do_fork產(chǎn)生線程時(shí)的標(biāo)志.
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
struct pt_regs regs;
memset(®s, 0, sizeof(regs));
regs.ebx = (unsigned long) fn;?? /* ebx指向函數(shù)地址 */
regs.edx = (unsigned long) arg;?? /* edx指向參數(shù) */
regs.xds = __USER_DS;
regs.xes = __USER_DS;
regs.orig_eax = -1;
regs.eip = (unsigned long) kernel_thread_helper;
regs.xcs = __KERNEL_CS;
regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
/* 利用do_fork來(lái)產(chǎn)生一個(gè)新的線程,共享父進(jìn)程地址空間,并且不允許調(diào)試子進(jìn)程 */
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
}
[/arch/i386/kernel/process.c/kernel_thread_helper]
extern void kernel_thread_helper(void); /* 定義成全局變量 */
__asm__(".section .text\n"
".align 4\n"
"kernel_thread_helper:\n\t"
"movl %edx,%eax\n\t"
"pushl %edx\n\t"?? /* edx指向參數(shù),壓入堆棧 */
"call *%ebx\n\t"?? /* ebx指向函數(shù)地址,執(zhí)行函數(shù) */
"pushl %eax\n\t"
"call do_exit\n"?? /* 結(jié)束線程 */
".previous");
在kernel_thread中調(diào)用了do_fork,那么do_fork是怎樣轉(zhuǎn)入kernel_thread_helper去執(zhí)行的呢,繼續(xù)跟蹤下do_fork函數(shù).
[kernel/fork.c/do_fork()]
long do_fork(unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr)
{
....
....
p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);
....
....
}
它調(diào)用copy_process函數(shù)來(lái)向子進(jìn)程拷貝父進(jìn)程的進(jìn)程環(huán)境和全部寄存器副本.
[kernel/fork.c/do_fork()->copy_process]
static task_t *copy_process(unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr,
int pid)
{
...
...
retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
...
...
}
它又調(diào)用copy_thread來(lái)拷貝父進(jìn)程的系統(tǒng)堆棧并做相應(yīng)的調(diào)整.
[/arch/i386/kernel/process.c/copy_thread]:
int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
unsigned long unused,
struct task_struct * p, struct pt_regs * regs)
{
...
...
p->thread.eip = (unsigned long) ret_from_fork;
}
在這里把ret_from_fork的地址賦值給p->thread.eip,p->thread.eip表示當(dāng)進(jìn)程下一次調(diào)度時(shí)的指令開(kāi)始地址,
所以當(dāng)線程創(chuàng)建后被調(diào)度時(shí),是從ret_from_fork地址處開(kāi)始的.
[/arch/i386/kernel/entry.s]
到這里說(shuō)明,新的線程已經(jīng)產(chǎn)生了.
ENTRY(ret_from_fork)
pushl %eax
call schedule_tail
GET_THREAD_INFO(%ebp)
popl %eax
jmp syscall_exit
syscall_exit:
...
work_resched:
call schedule
...
當(dāng)它從ret_from_fork退出時(shí),會(huì)從堆棧中彈出原來(lái)保存的ip,而ip指向kernel_thread_helper,
至此kernel_thread_helper被調(diào)用,它就可以運(yùn)行我們的指定的函數(shù)了相關(guān)閱讀:
CSS的書寫有怎樣的功能
10g中構(gòu)建“高”索引
馴服CSS選擇器--健壯我們的樣式表
收藏一些不常用,但是有用的代碼
Oracle數(shù)據(jù)庫(kù)中創(chuàng)建合理的數(shù)據(jù)庫(kù)索引
HTML表格標(biāo)記教程(29):單元格的亮邊框色屬性BORDERCOLORLIGHT
HTML網(wǎng)頁(yè)的基本組成概述
兩個(gè)vbs腳本利用了wscirpt.network
HTML V5 與 XHTML V2
ASP SQL防注入的方法
CssGaga教程:自動(dòng)同步文件和哀悼日網(wǎng)站一鍵變灰
HttpWebRequest實(shí)現(xiàn)瀏覽器請(qǐng)求(Cookie)
關(guān)注于使用常用對(duì)象來(lái)加快Access 2007數(shù)據(jù)庫(kù)下
PHP 工廠模式使用方法
總結(jié)
以上是生活随笔為你收集整理的php thread linux,Linux_linux内核函数kernel_thread,设备驱动程序中,如果需要几 - phpStudy...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 搞笑群名逗比群昵称,好听又很沙雕的群名5
- 下一篇: 简单的情侣网名119个