2012-04-16 34 views
10

Tôi đã nhìn thấy các bit của thông tin phân tán xung quanh, nhưng tôi dường như không thể có được một câu trả lời cuối cùng. Làm thế nào để bạn làm sạch một sợi zombie trong hạt nhân?Cách xử lý đúng luồng trong hạt nhân?

Chỉ để đảm bảo và tạo ra một cách xử lý chính xác cuối cùng các chuỗi trong hạt nhân, tôi muốn hỏi câu hỏi này rộng hơn. Làm thế nào để bạn tạo, chấm dứt và làm sạch một luồng trong hạt nhân Linux?

Những gì tôi có cho đến nay là thế này:

thread_func: 
    exited = 0; 
    while (!must_exit) 
     do stuff 
    exited = 1; 
    do_exit(0) 

init_module: 
    must_exit = 0; 
    exited = 1; 
    kthread_run(thread_func, ...) /* creates and runs the thread */ 

cleanup_module: 
    must_exit = 1; 
    while (!exited) 
     set_current_state(TASK_INTERRUPTIBLE); 
     msleep(1); 
    /* How do I cleanup? */ 

Điều gần nhất tôi đã tìm thấy các giải pháp dọn dẹp là release_task, nhưng tôi đã không tìm thấy bất cứ nơi nào nói về nó. Tôi tưởng tượng vì các chức năng của luồng là kthread_create, kthread_run v.v., phải có kthread_join hoặc kthread_wait, nhưng không có. do_wait cũng có vẻ như có khả năng, nhưng không mất struct task_struct *.

Hơn nữa, tôi không chắc chắn nếu do_exit là một ý tưởng hay, hoặc nếu cần thiết. Có thể ai đó vui lòng đưa ra phác thảo tối thiểu về việc làm thế nào một kthread nên được tạo ra, chấm dứt và làm sạch?

+2

Tôi dường như nhớ rằng có kthread_stop, hoặc kthread_should_stop, giống như vậy. –

+0

@MartinJames, theo cách tôi hiểu, bạn có thể thoát khỏi chính mình (sử dụng 'do_exit') hoặc thăm dò ý kiến' kthread_should_stop' cho đến khi ai đó ('cleanup_module') gọi' kthread_stop'. Tôi đã không tìm thấy bất cứ nơi nào nói rằng liệu 'kthread_stop' cũng làm sạch các chủ đề hay không. Điều gì làm tôi ngạc nhiên là, nếu mọi người (trên internet) đề nghị sử dụng 'do_exit' hoặc bất cứ điều gì, không nên có một cách để dọn dẹp sợi chỉ sau' do_exit'? – Shahbaz

+0

Bằng cách này, [this] (http://lwn.net/Articles/65178/) là những gì tôi nói về khi tôi nói tôi không thể đạt được một câu trả lời kết luận. Có rất nhiều thứ xung đột. – Shahbaz

Trả lời

11

Một trong những cách "đúng" để thực hiện việc này là kiểm tra chức năng chuỗi của bạn nếu nó kthread_should_stop và chỉ cần quay lại nếu cần dừng lại.

Bạn không cần gọi số do_exit và nếu bạn dự định kthread_stop từ chức năng thoát mô-đun, có thể bạn không nên.

Bạn có thể thấy điều này bằng cách nhìn vào tài liệu cho kthread_create_on_node trong kernel/kthread.c (chiết xuất từ ​​Linux kernel 3.3.1):

/**
* kthread_create_on_node - tạo ra một kthread.
* @threadfn: chức năng chạy cho đến khi signal_pending (hiện tại).
* @data: ptr dữ liệu cho @threadfn.
* @node: số nút bộ nhớ.
* @namefmt: tên kiểu printf cho chuỗi.
*
* Mô tả: Chức năng trợ giúp này tạo và đặt tên cho hạt nhân
* chuỗi. Chủ đề sẽ bị ngừng: sử dụng wake_up_process() để bắt đầu
*. Xem thêm kthread_run().
*
* Nếu chuỗi sẽ bị ràng buộc trên một cpu cụ thể, hãy cung cấp nút
* trong @node, để nhận được NUMA ái lực cho ngăn xếp kthread, hoặc đưa ra -1.
* Khi được đánh thức, chuỗi sẽ chạy @threadfn() với @data làm đối số
* của chúng tôi. @threadfn() hoặc có thể gọi do_exit() trực tiếp nếu nó là một chủ đề độc lập
* mà không ai sẽ gọi kthread_stop(), hoặc
* trở lại khi 'kthread_should_stop()' là đúng (có nghĩa là
* kthread_stop() đã được gọi). Giá trị trả lại phải bằng không
* hoặc số lỗi âm; nó sẽ được chuyển tới kthread_stop().
*
* Trả về một task_struct hoặc ERR_PTR (-ENOMEM).
*/

A "phù hợp với" bình luận được trình bày cho kthread_stop:

Nếu threadfn() có thể gọi do_exit() chính nó, người gọi phải đảm bảo task_struct không thể đi xa.

(Và tôi không chắc chắn làm thế nào bạn làm điều đó - có lẽ cầm sang struct_task với một get_task_struct.)

Nếu bạn bước đi trên con đường của một tạo thread bạn sẽ nhận được một cái gì đó như:

kthread_create           // macro in kthread.h 
    -> kthread_create_on_node        // in kthead.c 
    -> adds your thread request to kthread_create_list 
    -> wakes up the kthreadd_task 

kthreadd_task được thiết lập trong init/main.c trong reset_init. Nó chạy kthreadd chức năng (từ kthread.c)

kthreadd             // all in kthread.c 
    -> create_kthread 
    -> kernel_thread(kthread, your_kthread_create_info, ...) 

kthread chức năng chính nó:

kthread 
    -> initialization stuff 
    -> schedule() // allows you to cancel the thread before it's actually started 
    -> if (!should_stop) 
    -> ret = your_thread_function() 
    -> do_exit(ret) 

... Vì vậy, nếu chỉ đơn giản trả your_thread_function, do_exit sẽ được gọi với giá trị trả về của nó. Không cần phải tự mình làm.

+0

Vâng, cấu trúc nhiệm vụ là một biến toàn cầu, vì vậy nó không thể đi bất cứ đâu. Nhưng, điều này có nghĩa là nếu thread độc lập gọi 'do_exit()' (và do đó không nên gọi 'kthread_stop') nó sẽ không cần dọn dẹp? – Shahbaz

+0

Nó có thể đi nơi. Nếu nhiệm vụ mà nhiệm vụ struct đó đề cập đến là hoàn toàn được thực hiện, và cấu trúc nhiệm vụ được giải thoát bởi đường dẫn thoát, bản sao bạn có trong dữ liệu mô-đun của bạn giống như một con trỏ lơ lửng - bạn không thể sử dụng nó. – Mat

+0

Và có, nếu bạn không có ý định 'kthread_stop' chủ đề của bạn, nó có thể gọi' do_exit' và dọn dẹp bình thường sẽ xảy ra. _But_ Nếu bằng cách nào đó luồng của bạn quản lý để tồn tại mô-đun của bạn, bạn đang gặp rắc rối. – Mat

Các vấn đề liên quan