2012-10-19 3 views
4

나는 커널 모듈 프로그래밍에 익숙하지 않다. 그리고 나는 다중 쓰레드 커널 모듈을 작성해야한다. 그래서 커널 스레드의 주요 용도를 시도했습니다. 나는 다음과 같이 썼다. 하나의 스레드에 1을 인쇄하고 다른 스레드에 2를 10 번 인쇄합니다.간단한 커널 다중 쓰레드

#include <linux/module.h> 
#include <linux/moduleparam.h> 
#include <linux/kernel.h> 
#include <linux/udp.h> 
#include <linux/mm.h> 
#include <linux/init.h> 
#include <linux/kthread.h> 

struct task_struct *task1; 
struct task_struct *task2; 


static void thread_func(void* data) 
{ 
    int *n; 
    n = (int *)data; 
    int i = 0; 
    while(i < 10){ 
     printk("%d\n", *n); 
     i++; 
    } 
    //do_exit(); 
} 

static int t_start(void) 
{ 
    printk("Module starting ... ... ..\n"); 
    int *p1, *p2; 
    int one = 1, two = 2; 
    p1 = &one; 
    p2 = &two; 
    task1 = kthread_run(&thread_func, (void*)p1, "thread_func_1"); 
    task2 = kthread_run(&thread_func, (void*)p2, "thread_func_2"); 
    return 0; 
} 

static void t_end (void) 
{ 
    printk("Module terminating ... ... ...\n"); 
    kthread_stop(task1); 
    kthread_stop(task2); 
} 

module_init(t_start); 
module_exit(t_end); 

MODULE_AUTHOR("Md. Taufique Hussain"); 
MODULE_DESCRIPTION("Testing kernel threads"); 
MODULE_LICENSE("GPL"); 

하지만 다음과 같은 문제가 있습니다. -

  1. 첫 번째 스레드는 10 개의 1을 모두 인쇄하고 두 번째 스레드는 입니다. 이 두 가지를 인터리브 방식으로 실행하고 싶었습니다.
  2. 첫 번째 스레드는 모두 1을 인쇄하지만 OK는 2 초를 인쇄하지 않습니다. 은 0을 인쇄 중입니다. 아마도 매개 변수가 두 번째 스레드 으로 제대로 전달되지 않습니다.
  3. 나는 그것을 실행 모듈을 삽입하고하지만 난 모듈을 제거하고 때 기계는 문제가 무엇입니까

을 중단? 어떻게 해결할 수 있습니까?

+1

은이 질문에 다른 사람이 보면, 함수의 반환 형식은'thread_func'는'int'이어야합니다. – omerjerk

답변

2

schedule을 호출하여 스레드 예약을 강제로 호출하십시오. 당신이 선점 형 커널과 약간의 잠을하지 않는

static void thread_func(void* data) 
{ 
    int *n; 
    n = (int *)data; 
    int i = 0; 
    while(i < 10){ 
     printk("%d\n", *n); 

     schedule(); 

     i++; 
    } 
    //do_exit(); 
} 
+0

세 번째 문제는 무엇입니까? 그것의 가장 성가신. – taufique

+0

'task1'과'task2'는 스레드가 완료된 후 잘못된 포인터입니다. 스레드 종료 및 모듈 언로드를 sinchronize해야합니다. –

+1

루프 안에'schedule();'을 추가했습니다. 그러나 여전히 동일합니다. – taufique

1
  1. 당신은 일정을()가 필요합니다.
  2. 스택에서 데이터 포인터를 전달하므로 커널 메모리가 손상됩니다. 그 int 전역 변수를 확인하십시오.
+0

커널 스레드에서 전역 변수보다 함수에서 데이터를 전달하는 것이 문제가됩니까? 그 대답은 – taufique

+0

+1입니다! 물론, 현재 커널 메모리에서 임의의 스레드로 스택 포인터를 전달하는 것은 불가능합니다. –

+0

@IlyaMatveychikov - 구조체를 보내야하는 경우 Wat ?? 위의 예제에서 int 값을 전달하더라도이를 수행합니다. 그러나 구조 나 배열은 어떨까요? – codingfreak

1

1.Don't은 널 포인터의 원인이됩니다)

는 스레드의 종료 후 보인다
// kthread_stop(task1); 
// kthread_stop(task2); 

이 작업이 다음 (kthread_stop 호출, null로 설정됩니다를 삭제하려면 다음 코드를 사용 오류

2. 지역 변수를 스레드에 전달하지 마십시오. 전역 변수를 대신 사용하십시오.

3. 두 스레드가 서로 전환되도록하려면 "wait_event"및 "wake_up"기능을 사용하십시오. 작동하는 코드는 다음과 같습니다. 경우

#include <linux/init.h> 
#include <linux/module.h> 
#include <linux/kernel.h> 
#include <linux/sched.h> 
#include <linux/kthread.h> 
#include <linux/wait.h> 

MODULE_LICENSE("GPL"); 


int pid1 = 1; 
int pid2 = 2; 

DECLARE_WAIT_QUEUE_HEAD(wq); 

int condition; 

struct task_struct *task1; 
struct task_struct *task2; 

static int thread_function(void *data){ 

    int *thread_id = (int*)data; 
    int i = 0; 
    while(i < 10){ 
     printk(KERN_INFO "install kernel thread: %d\n", *thread_id); 
     i++; 

     if(*thread_id == 1) 
     { 
      wait_event(wq, condition == 0xA); 

      condition = 0xB; 
      wake_up(&wq); 
     } 
     else{ 
      wait_event(wq, condition == 0xB); 

      condition = 0xA; 
      wake_up(&wq); 
     } 
    } 
    return 0; 
} 


static int kernel_init(void) 
{ 
    condition = 0xA; 

    task1 = kthread_create(&thread_function, (void *)&pid1, "pradeep"); 
    task2 = kthread_create(&thread_function, (void *)&pid2, "pradeep"); 

    //printk(KERN_INFO "After create kernel thread\n"); 
    wake_up_process(task1); 
    wake_up_process(task2); 
    return 0; 
} 

int init_module(void) 
{ 
    kernel_init(); 
    return 0; 
} 

void cleanup_module(void) 
{ 
    return; 
} 

관련 문제