• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 297,  comments - 15,  trackbacks - 0
            Linux Kernel Threads in Device Drivers 
            Purpose 
            This examples shows how to create and stop a kernel thread. 
            The driver is implemented as a loadable module. In the init_module() routine five kernel threads are created. This kernel threads sleep one second, wake up, print a message and fall asleep again. On unload of the module (cleanup_module), the kernel threads are killed. 
            The example has been tested with Linux kernel 2.4.2 on Intel (uni processor only) and Alpha platform (COMPAQ Personal Workstation 500au (uni processor), DS20 and ES40 (SMP). 
            A version for the 2.2 kernel can be found here. Note: depending on the context of the creator of the threads the new threads may inherit properties from the parent you do not want to have. The new version avoids this by having keventd create the threads. The 2.2. kernel do not have a keventd, so this approach is not implementable there. 

            Functions in example 
            start_kthread: creates a new kernel thread. Can be called from any process context but not from interrupt. The functions blocks until the thread started. 
            stop_kthread: stop the thread. Can be called from any process context but the thread to be terminated. Cannot be called from interrupt context. The function blocks until the thread terminated. 
            init_kthread: sets the environment of the new threads. Is to be called out of the created thread. 
            exit_kthread: needs to be called by the thread to be terminated on exit 
            Creation of new Thread 
            A new thread is created with kernel_thread(). The thread inherits properties from its parents. To make sure that we do not get any weired properties, we let keventd create the new thread. 
            The new thread is created with start_kthread(). It uses a semaphore to block until the new thread is running. A down() blocks the start_kthread() routine until the corresponding up() call in init_kthread() is executed. 
            The new thread must call init_kthread() in order to let the creator continue. 
            Stop of new Thread 
            stop_kthread() sets a flag that the thread uses to determine whether do die or not and sends a SIGKILL to the thread. This signal causes the thread to be woken up. On wakeup it will check for the flag and then terminate itself by calling exit_kthread and returning from the thread function. With a semaphore the stop_kthread() function blocks until the thread terminated. 
            Initialization of new Thread 
            Within the new created thread, init_kthread() needs to be called. This function sets a signal mask, initialises a wait queue, the termination flag and sets a new name for the thread. With a up() call it notifies the creator that the setup is done. 
            Exit of new Thread 
            When the thread receives the notification to terminate itself, is calls the exit_kthread() function. It notifies the stop_kthread() function that it terminated with an up() call. 
            The new Thread itself 
            The new thread is implemented in the example_thread() function. It runs an endless loop (for(;;)). In the loop it falls asleep with the interruptible_sleep_on_timeout() function. It comes out of this function either when the timeout expires or when a signal got caught. 
            The "work" in the thread is to print out a message with printk. 
            Kernel Versions 
            The example has been tested on 2.4.2. 
            Example Device Driver Code 
            The example consists of four files: kthread.h, kthread.c, thread_drv.c and a Makefile 
            kthread.h 
            #ifndef _KTHREAD_H 
            #define _KTHREAD_H 
            #include <linux/config.h> 
            #include <linux/version.h> 

            #include <linux/kernel.h> 
            #include <linux/sched.h> 
            #include <linux/tqueue.h> 
            #include <linux/wait.h> 

            #include <asm/unistd.h> 
            #include <asm/semaphore.h> 

            /* a structure to store all information we need 
            for our thread */ 
            typedef struct kthread_struct 
            { 
            /* private data */ 

            /* Linux task structure of thread */ 
            struct task_struct *thread; 
            /* Task queue need to launch thread */ 
            struct tq_struct tq; 
            /* function to be started as thread */ 
            void (*function) (struct kthread_struct *kthread); 
            /* semaphore needed on start and creation of thread. */ 
            struct semaphore startstop_sem; 

            /* public data */ 

            /* queue thread is waiting on. Gets initialized by 
            init_kthread, can be used by thread itself. 
            */ 
            wait_queue_head_t queue; 
            /* flag to tell thread whether to die or not. 
            When the thread receives a signal, it must check 
            the value of terminate and call exit_kthread and terminate 
            if set. 
            */ 
            int terminate; 
            /* additional data to pass to kernel thread */ 
            void *arg; 
            } kthread_t; 

            /* prototypes */ 

            /* start new kthread (called by creator) */ 
            void start_kthread(void (*func)(kthread_t *), kthread_t *kthread); 

            /* stop a running thread (called by "killer") */ 
            void stop_kthread(kthread_t *kthread); 

            /* setup thread environment (called by new thread) */ 
            void init_kthread(kthread_t *kthread, char *name); 

            /* cleanup thread environment (called by thread upon receiving termination signal) */ 
            void exit_kthread(kthread_t *kthread); 

            #endif 

            kthread.c 
            #include <linux/config.h> 
            #include <linux/version.h> 

            #if defined(MODVERSIONS) 
            #include <linux/modversions.h> 
            #endif 
            #include <linux/kernel.h> 
            #include <linux/sched.h> 
            #include <linux/tqueue.h> 
            #include <linux/wait.h> 
            #include <linux/signal.h> 

            #include <asm/semaphore.h> 
            #include <asm/smplock.h> 

            #include "kthread.h" 

            /* private functions */ 
            static void kthread_launcher(void *data) 
            { 
            kthread_t *kthread = data; 
            kernel_thread((int (*)(void *))kthread->function, (void *)kthread, 0); 

            } 

            /* public functions */ 

            /* create a new kernel thread. Called by the creator. */ 
            void start_kthread(void (*func)(kthread_t *), kthread_t *kthread) 
            { 
            /* initialize the semaphore: 
            we start with the semaphore locked. The new kernel 
            thread will setup its stuff and unlock it. This 
            control flow (the one that creates the thread) blocks 
            in the down operation below until the thread has reached 
            the up() operation. 
            */ 
            init_MUTEX_LOCKED(&kthread->startstop_sem); 

            /* store the function to be executed in the data passed to 
            the launcher */ 
            kthread->function=func; 

            /* create the new thread my running a task through keventd */ 

            /* initialize the task queue structure */ 
            kthread->tq.sync = 0; 
            INIT_LIST_HEAD(&kthread->tq.list); 
            kthread->tq.routine = kthread_launcher; 
            kthread->tq.data = kthread; 

            /* and schedule it for execution */ 
            schedule_task(&kthread->tq); 

            /* wait till it has reached the setup_thread routine */ 
            down(&kthread->startstop_sem); 

            } 

            /* stop a kernel thread. Called by the removing instance */ 
            void stop_kthread(kthread_t *kthread) 
            { 
            if (kthread->thread == NULL) 
            { 
            printk("stop_kthread: killing non existing thread!\n"); 
            return; 
            } 

            /* this function needs to be protected with the big 
            kernel lock (lock_kernel()). The lock must be 
            grabbed before changing the terminate 
            flag and released after the down() call. */ 
            lock_kernel(); 

            /* initialize the semaphore. We lock it here, the 
            leave_thread call of the thread to be terminated 
            will unlock it. As soon as we see the semaphore 
            unlocked, we know that the thread has exited. 
            */ 
            init_MUTEX_LOCKED(&kthread->startstop_sem); 

            /* We need to do a memory barrier here to be sure that 
            the flags are visible on all CPUs. 
            */ 
            mb(); 

            /* set flag to request thread termination */ 
            kthread->terminate = 1; 

            /* We need to do a memory barrier here to be sure that 
            the flags are visible on all CPUs. 
            */ 
            mb(); 
            kill_proc(kthread->thread->pid, SIGKILL, 1); 

            /* block till thread terminated */ 
            down(&kthread->startstop_sem); 

            /* release the big kernel lock */ 
            unlock_kernel(); 

            /* now we are sure the thread is in zombie state. We 
            notify keventd to clean the process up. 
            */ 
            kill_proc(2, SIGCHLD, 1); 

            } 

            /* initialize new created thread. Called by the new thread. */ 
            void init_kthread(kthread_t *kthread, char *name) 
            { 
            /* lock the kernel. A new kernel thread starts without 
            the big kernel lock, regardless of the lock state 
            of the creator (the lock level is *not* inheritated) 
            */ 
            lock_kernel(); 

            /* fill in thread structure */ 
            kthread->thread = current; 

            /* set signal mask to what we want to respond */ 
            siginitsetinv(&current->blocked, sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)); 

            /* initialise wait queue */ 
            init_waitqueue_head(&kthread->queue); 

            /* initialise termination flag */ 
            kthread->terminate = 0; 

            /* set name of this process (max 15 chars + 0 !) */ 
            sprintf(current->comm, name); 

            /* let others run */ 
            unlock_kernel(); 

            /* tell the creator that we are ready and let him continue */ 
            up(&kthread->startstop_sem); 

            } 

            /* cleanup of thread. Called by the exiting thread. */ 
            void exit_kthread(kthread_t *kthread) 
            { 
            /* we are terminating */ 

            /* lock the kernel, the exit will unlock it */ 
            lock_kernel(); 
            kthread->thread = NULL; 
            mb(); 

            /* notify the stop_kthread() routine that we are terminating. */ 
            up(&kthread->startstop_sem); 
            /* the kernel_thread that called clone() does a do_exit here. */ 

            /* there is no race here between execution of the "killer" and real termination 
            of the thread (race window between up and do_exit), since both the 
            thread and the "killer" function are running with the kernel lock held. 
            The kernel lock will be freed after the thread exited, so the code 
            is really not executed anymore as soon as the unload functions gets 
            the kernel lock back. 
            The init process may not have made the cleanup of the process here, 
            but the cleanup can be done safely with the module unloaded. 
            */ 

            } 

            thread_drv.c 
            #include <linux/config.h> 
            #include <linux/version.h> 

            #include <linux/module.h> 
            #if defined(MODVERSIONS) 
            #include <linux/modversions.h> 
            #endif 

            #include <linux/kernel.h> 
            #include <linux/string.h> 
            #include <linux/errno.h> 
            #include <linux/sched.h> 

            #include "kthread.h" 

            #define NTHREADS 5 

            /* the variable that contains the thread data */ 
            kthread_t example[NTHREADS]; 

            /* prototype for the example thread */ 
            static void example_thread(kthread_t *kthread); 

            /* load the module */ 
            int init_module(void) 
            { 
            int i; 

            /* create new kernel threads */ 
            for (i=0; i <NTHREADS; i++) 
            start_kthread(example_thread, &example); 

            return(0); 
            } 

            /* remove the module */ 
            void cleanup_module(void) 
            { 
            int i; 

            /* terminate the kernel threads */ 
            for (i=0; i<NTHREADS; i++) 
            stop_kthread(&example); 

            return; 
            } 

            /* this is the thread function that we are executing */ 
            static void example_thread(kthread_t *kthread) 
            { 
            /* setup the thread environment */ 
            init_kthread(kthread, "example thread"); 

            printk("hi, here is the kernel thread\n"); 

            /* an endless loop in which we are doing our work */ 
            for(;;) 
            { 
            /* fall asleep for one second */ 
            interruptible_sleep_on_timeout(&kthread->queue, HZ); 

            /* We need to do a memory barrier here to be sure that 
            the flags are visible on all CPUs. 
            */ 
            mb(); 

            /* here we are back from sleep, either due to the timeout 
            (one second), or because we caught a signal. 
            */ 
            if (kthread->terminate) 
            { 
            /* we received a request to terminate ourself */ 
            break; 
            } 

            /* this is normal work to do */ 
            printk("example thread: thread woke up\n"); 
            } 
            /* here we go only in case of termination of the thread */ 

            /* cleanup the thread, leave */ 
            exit_kthread(kthread); 

            /* returning from the thread here calls the exit functions */ 
            } 

            Makefile 
            # set to your kernel tree 
            KERNEL = /usr/src/linux 

            # get the Linux architecture. Needed to find proper include file for CFLAGS 
            ARCH=$(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
            # set default flags to compile module 
            CFLAGS = -D__KERNEL__ -DMODULE -I$(KERNEL)/include 
            CFLAGS+= -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing 

            all: thread_mod.o 

            # get configuration of kernel 
            include $(KERNEL)/.config 
            # modify CFLAGS with architecture specific flags 
            include $(KERNEL)/arch/${ARCH}/Makefile 

            # enable the module versions, if configured in kernel source tree 
            ifdef CONFIG_MODVERSIONS 
            CFLAGS+= -DMODVERSIONS -include $(KERNEL)/include/linux/modversions.h 
            endif 
            # enable SMP, if configured in kernel source tree 
            ifdef CONFIG_SMP 
            CFLAGS+= -D__SMP__ 
            endif 

            # note: we are compiling the driver object file and then linking 
            # we link it into the module. With just one object file as in 
            # this example this is not needed. We can just load the object 
            # file produced by gcc 
            # link the thread driver module 
            thread_mod.o: thread_drv.o kthread.o 
            ld -r -o thread_mod.o thread_drv.o kthread.o 
            # compile the kthread object file 
            kthread.o: kthread.c kthread.h 
            gcc $(CFLAGS) -c kthread.c 
            # compile the thread driver 
            thread_drv.o: thread_drv.c kthread.h 
            gcc $(CFLAGS) -c thread_drv.c 

            clean: 
            rm -f *.o 

            Bugs 
            The code assumes that keventd is running with PID 2. 
            Comments, Corrections 
            Please send comments, corrections etc. to the address below.

            from:
            http://www.linuxforum.net/forum/showflat.php?Cat=&Board=linuxK&Number=282973&page=15&view=collapsed&sb=5&o=all


            posted on 2011-03-22 21:08 chatler 閱讀(690) 評論(0)  編輯 收藏 引用 所屬分類: linux kernel
            <2025年7月>
            293012345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789

            常用鏈接

            留言簿(10)

            隨筆分類(307)

            隨筆檔案(297)

            algorithm

            Books_Free_Online

            C++

            database

            Linux

            Linux shell

            linux socket

            misce

            • cloudward
            • 感覺這個博客還是不錯,雖然做的東西和我不大相關,覺得看看還是有好處的

            network

            OSS

            • Google Android
            • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
            • os161 file list

            overall

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            狠狠狠色丁香婷婷综合久久俺| 久久国产精品77777| 久久国产午夜精品一区二区三区| 久久99热狠狠色精品一区| 青青热久久综合网伊人| 久久久这里有精品中文字幕| 久久天天躁夜夜躁狠狠| 青青青青久久精品国产h| 亚洲天堂久久久| 青草影院天堂男人久久| 久久精品一本到99热免费| 好久久免费视频高清| 久久人妻少妇嫩草AV蜜桃| 色偷偷888欧美精品久久久| 性高湖久久久久久久久AAAAA| 久久午夜羞羞影院免费观看| 热久久这里只有精品| 亚洲女久久久噜噜噜熟女| 久久综合狠狠综合久久97色| 97久久超碰成人精品网站| 久久伊人五月丁香狠狠色| 亚洲狠狠综合久久| 精品无码久久久久国产| 无码国内精品久久综合88| 精品久久久无码中文字幕天天 | 久久国产欧美日韩精品| 99久久婷婷国产综合精品草原| 色欲久久久天天天综合网| 一级做a爰片久久毛片免费陪| 99久久精品免费看国产| 亚洲一区中文字幕久久| 久久电影网一区| 久久婷婷国产麻豆91天堂| 国内精品人妻无码久久久影院 | 久久久久这里只有精品 | 久久久久无码中| 狠狠色丁香婷婷综合久久来来去 | 久久久久高潮综合影院| 久久精品国产色蜜蜜麻豆| 精品综合久久久久久98| 久久成人国产精品免费软件|