定義在頭文件asm/atomic.h中; 原子操作指的是在執(zhí)行過程中不會被別的代碼路徑所打斷的操作; Linux內核提供了一系列的函數來實現內核中的原子操作,這些函數又分為兩類,分別針對位變量和整型變量進行原子操作;它們的共同點是:在任何情況下操作都是原子的,內核代碼可以安全地調用它們而不會被打斷;位變量和整型變量的原子操作都依賴于底層CPU的原子操作來實現,因此所有這些函數都是與CPU架構密切相關; 使用原子變量的操作,可以使設備最多只能被一個進程打開; 一,、整型原子變量操作 1).設置原子變量的值: void atomic_set(atomic_t* v, int i); //設置原子變量v的值為i; atomic_t v = ATOMIC_INIT(0); //定義原子變量v,并初始化為0; 2).獲取原子變量的值: atomic_read(atomic_t* v); //返回原子變量v的值; 3).原子變量加/減: void atomic_add(int i, atomic_t* v); //原子變量v增加i; void atomic_sub(int i, atomic_t* v); //原子變量v減少i; 4).原子變量自增/自減: void atomic_inc(atomic_t* v); //原子變量增加1; void atomic_dec(atomic_t* v); //原子變量自減1; 5).操作并測試: int atomic_inc_and_test(atomic_t* v); //先自增1,然后測試其值是否為0,若為0,則返回true,否則返回false; int atomic_dec_and_test(atomic_t* v); //先自減1,然后測試其值是否為0,若為0,則返回true,否則返回false; int atomic_sub_and_test(int i, atomic_t* v); //先加i,然后測試其值是否為0,若為0,則返回true,否則返回false; 6).操作并返回: int atomic_add_return(int i, atomic_t* v); //v的值加i后返回新的值; int atomic_sub_return(int i, atomic_t* v); //v的值減i后返回新的值; int atomic_inc_return(atomic_t* v); //v的值自增1后返回新的值; int atomic_dec_return(atomic_t* v); //v的值自減1后返回新的值; 二、位原子變量操作 1).設置/清除位: void set_bit(int nr, volatile void* addr); //設置地址addr的第nr位,所謂設置位,就是把位寫為1; void clear_bit(int nr, volatile void* addr); //清除地址addr的第nr位,所謂清除位,就是把位寫為0; 2).改變位: void change_bit(int nr, volatile void* addr); //把地址addr的第nr位反轉; 3).測試位: int test_bit(int nr, volatile void* addr); //返回地址addr的第nr位; 4).測試并操作位: int test_and_set_bit(int nr, volatile void* addr); //測試并設置位;若addr的第nr位非0,則返回true; 若addr的第nr位為0,則返回false; int test_and_clear_bit(int nr, volatile void* addr); //測試并清除位;若addr的第nr位非0,則返回true; 若addr的第nr位為0,則返回false; int test_and_change_bit(int nr, volatile void* addr); //測試并反轉位;若addr的第nr位非0,則返回true; 若addr的第nr位為0,則返回false; 注意:位變量的操作函數中的參數nr的取值從0開始計算:[0,7]或[0,15]或[0,31]或[0,63]; 例子: #include <linux/module.h> #include <linux/version.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/jiffies.h> #include <linux/delay.h> //這三個頭文件與內核線程的使用有關; #include <linux/sched.h> #include <linux/kthread.h> #include <linux/err.h> //原子操作相關 #include <asm/atomic.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("*************"); MODULE_VERSION("2.6.35.000"); static int sleep_time = (1*10*HZ); static atomic_t shared_res; static unsigned int bit_var = 3; //STEP5:實現線程函數 static int thread_process1(void* param) { int val = 0, ret = 0; while(1) { set_current_state(TASK_UNINTERRUPTIBLE); if(kthread_should_stop()) { printk("kernel thread '%s' should stop;file:%s;line:%d\n", __FUNCTION__, __FILE__, __LINE__); break; } set_bit(0, (volatile void*)&bit_var); printk("%s: set bit_var = %u;\n", __FUNCTION__, bit_var); clear_bit(0, (volatile void*)&bit_var); printk("%s: clear bit_var = %u;\n", __FUNCTION__, bit_var); //atomic_add(1, &shared_res); //val = atomic_read(&shared_res); //val = atomic_add_return(1, &shared_res); //val = atomic_inc_return(&shared_res); ret = atomic_inc_and_test(&shared_res); val = atomic_read(&shared_res); printk("%s: shared resource = %d, true=%d;\n%s", __FUNCTION__, val, ret, ((val % 3) ? "" : "\n")); mdelay(sleep_time); } return 123; }; static int thread_process2(void* param) { int val = 0, ret = 0; while(1) { set_current_state(TASK_UNINTERRUPTIBLE); if(kthread_should_stop()) { printk("kernel thread '%s' should stop;file:%s;line:%d\n", __FUNCTION__, __FILE__, __LINE__); break; } set_bit(0, (volatile void*)&bit_var); printk("%s: set bit_var = %u;\n", __FUNCTION__, bit_var); clear_bit(0, (volatile void*)&bit_var); printk("%s: clear bit_var = %u;\n", __FUNCTION__, bit_var); //atomic_add(1, &shared_res); //val = atomic_read(&shared_res); //val = atomic_add_return(1, &shared_res); //val = atomic_inc_return(&shared_res); ret = atomic_inc_and_test(&shared_res); val = atomic_read(&shared_res); printk("%s: shared resource = %d, true=%d;\n%s", __FUNCTION__, val, ret, ((val % 3) ? "" : "\n")); msleep(sleep_time); } return 456; }; static int thread_process3(void* param) { int val = 0, ret = 0; while(1) { set_current_state(TASK_UNINTERRUPTIBLE); if(kthread_should_stop()) { printk("kernel thread '%s' should stop;file:%s;line:%d\n", __FUNCTION__, __FILE__, __LINE__); break; } set_bit(0, (volatile void*)&bit_var); printk("%s: set bit_var = %u;\n", __FUNCTION__, bit_var); clear_bit(0, (volatile void*)&bit_var); printk("%s: clear bit_var = %u;\n", __FUNCTION__, bit_var); //atomic_add(1, &shared_res); //val = atomic_read(&shared_res); //val = atomic_add_return(1, &shared_res); //val = atomic_inc_return(&shared_res); ret = atomic_inc_and_test(&shared_res); val = atomic_read(&shared_res); printk("%s: shared resource = %d, true=%d;\n%s", __FUNCTION__, val, ret, ((val % 3) ? "" : "\n")); msleep(sleep_time); } return 789; }; static struct task_struct* my_thread1 = NULL; static struct task_struct* my_thread2 = NULL; static struct task_struct* my_thread3 = NULL; static int __init study_init(void) { int err = 0; printk("%s\n", __PRETTY_FUNCTION__); //shared_res = ATOMIC_INIT(0); //printk("int-atomic ATOMIC_INIT=%d\n", atomic_read(&shared_res)); atomic_set(&shared_res, -100); printk("int-atomic atomic_set=%d\n", atomic_read(&shared_res)); my_thread1 = kthread_create(thread_process1, NULL, "my_thread1"); if(IS_ERR(my_thread1)) { err = PTR_ERR(my_thread1); my_thread1 = NULL; printk(KERN_ERR "unable to start kernel thread1:%d\n", err); return err; } my_thread2 = kthread_create(thread_process2, NULL, "my_thread2"); if(IS_ERR(my_thread2)) { err = PTR_ERR(my_thread2); my_thread2 = NULL; printk(KERN_ERR "unable to start kernel thread2:%d\n", err); return err; } my_thread3 = kthread_create(thread_process3, NULL, "my_thread3"); if(IS_ERR(my_thread3)) { err = PTR_ERR(my_thread3); my_thread3 = NULL; printk(KERN_ERR "unable to start kernel thread3:%d\n", err); return err; } wake_up_process(my_thread1); wake_up_process(my_thread2); wake_up_process(my_thread3); printk("%s:all kernel thread start;\n", __FUNCTION__); return 0; } static void __exit study_exit(void) { int ret = -1; printk("%s\n",__PRETTY_FUNCTION__); if(my_thread1) { ret = kthread_stop(my_thread1); my_thread1 = NULL; printk("kernel thread1 stop,exit code is %d;\n",ret); } if(my_thread2) { ret = kthread_stop(my_thread2); my_thread2 = NULL; printk("kernel thread2 stop,exit code is %d;\n",ret); } if(my_thread3) { ret = kthread_stop(my_thread3); my_thread3 = NULL; printk("kernel thread3 stop,exit code is %d;\n",ret); } printk("%s:all kernel thread stop;\n", __FUNCTION__); } module_init(study_init); module_exit(study_exit);
|