Linux驱动:信号量同步测试


环境:

主机:Fedora12

目标板:MINI6410

目标板LINUX内核版本:2.6.38


信号量主要函数:

//定义信号量

struct semaphore sem;

//初始化信号量

void sema_init(struct semaphore *sem,int val);

//获得信号量,会导致睡眠,不可在中断中使用

void down(struct semaphore *sem);

//获得信号量,能被信号打断,返回0表示正常返回,返回-EINTR表示被信号打断

int down_interruptible(struct semaphore *sem);

//尝试获得信号量sem,如果能够立即获得,返回0,否则返回非0值,它不会导致调用者睡眠,可以在中断上下文使用

int down_trylock(struct semaphore *sem);

//释放信号,唤醒等待者

void up(struct semaphore *sem);


测试代码:

[cpp]
  1. #include <linux/miscdevice.h>   
  2. #include <linux/delay.h>   
  3. #include <asm/irq.h>   
  4. //#include <mach/regs-gpio.h>   
  5. #include <mach/hardware.h>   
  6. #include <linux/kernel.h>   
  7. #include <linux/module.h>   
  8. #include <linux/init.h>   
  9. #include <linux/mm.h>   
  10. #include <linux/fs.h>   
  11. #include <linux/types.h>   
  12. #include <linux/delay.h>   
  13. #include <linux/moduleparam.h>   
  14. #include <linux/slab.h>   
  15. #include <linux/errno.h>   
  16. #include <linux/ioctl.h>   
  17. #include <linux/cdev.h>   
  18. #include <linux/string.h>   
  19. #include <linux/list.h>   
  20. #include <linux/pci.h>   
  21. #include <asm/uaccess.h>   
  22. #include <asm/atomic.h>   
  23. #include <asm/unistd.h>   
  24. #include <linux/major.h>   
  25.   
  26. #include <mach/map.h>   
  27. #include <mach/regs-clock.h>   
  28. #include <mach/regs-gpio.h>   
  29.   
  30. #include <plat/gpio-cfg.h>   
  31. #include <mach/gpio-bank-e.h>   
  32. #include <mach/gpio-bank-k.h>   
  33. #include <mach/gpio-bank-h.h>   
  34. #include <mach/gpio-bank-n.h>   
  35. #include <mach/gpio-bank-l.h>   
  36. #include <mach/gpio-bank-p.h>   
  37.   
  38. #include <linux/device.h>   
  39.   
  40. #include <linux/jiffies.h>   
  41.   
  42. #define DEVICE_NAME "led_driver"   
  43. #define T_MAJORS    700   
  44.   
  45. static struct cdev fun_cdev;  
  46. static dev_t dev;  
  47. static struct class    *led_class;  
  48.   
  49. struct semaphore sem;  
  50.   
  51. //功能:初始化IO   
  52. static void init_led(void)  
  53. {  
  54.     unsigned temp;  
  55.   
  56.     //GPK4-7设置为输出   
  57.     temp = readl(S3C64XX_GPKCON);  
  58.     temp &= ~((0xf << 4) | (0xf << 5) | (0xf << 6) | (0xf<< 7));  
  59.     temp |= (1 << 16) | (1 << 20) | (1 << 24) | (1 << 28);  
  60.     writel(temp, S3C64XX_GPKCON);  
  61. }  
  62.   
  63. //功能:ioctl操作函数   
  64. //返回值:成功返回0   
  65. static long led_driver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  
  66. {  
  67.     unsigned int temp = 0;  
  68.     //unsigned long t = 0;   
  69.     wait_queue_head_t wait;  
  70.   
  71.     //获取信号量   
  72.     if (down_interruptible(&sem))  
  73.     {  
  74.         return -1;  
  75.     }  
  76.       
  77.     temp = readl(S3C64XX_GPKDAT);  
  78.     if (cmd == 0)  
  79.     {  
  80.         temp &= ~(1 << (arg + 3));  
  81.     }  
  82.     else  
  83.     {  
  84.         temp |= 1 << (arg + 3);  
  85.     }  
  86.   
  87.     //等待2S   
  88.     //t = jiffies;   
  89.     //while (time_after(jiffies,t + 2 * HZ) != 1);   
  90.     init_waitqueue_head(&wait);  
  91.     sleep_on_timeout(&wait,2 * HZ);  
  92.     writel(temp,S3C64XX_GPKDAT);  
  93.   
  94.     printk (DEVICE_NAME"\tjdh:led_driver cmd=%d arg=%d jiffies = %d\n",cmd,arg,jiffies);  
  95.   
  96.     //释放信号量   
  97.     up(&sem);  
  98.       
  99.     return 0;  
  100. }  
  101.   
  102. static struct file_operations io_dev_fops = {  
  103.     .owner = THIS_MODULE,  
  104.     .unlocked_ioctl = led_driver_ioctl,  
  105. };  
  106.   
  107. static int __init dev_init(void)  
  108. {  
  109.     int ret;  
  110.     unsigned temp;  
  111.   
  112.     init_led();  
  113.   
  114.     dev = MKDEV(T_MAJORS,0);  
  115.     cdev_init(&fun_cdev,&io_dev_fops);  
  116.     ret = register_chrdev_region(dev,1,DEVICE_NAME);  
  117.     if (ret < 0) return 0;  
  118.     ret = cdev_add(&fun_cdev,dev,1);  
  119.     if (ret < 0) return 0;  
  120.   
  121.     printk (DEVICE_NAME"\tjdh:led_driver initialized!!\n");  
  122.   
  123.     led_class = class_create(THIS_MODULE, "led_class1");   
  124.     if (IS_ERR(led_class))   
  125.     {   
  126.         printk(KERN_INFO "create class error\n");   
  127.         return -1;   
  128.     }   
  129.     device_create(led_class, NULL, dev, NULL, "led_driver");   
  130.   
  131.     //初始化信号量   
  132.     sema_init(&sem,1);  
  133.   
  134.     return ret;  
  135. }  
  136.   
  137. static void __exit dev_exit(void)  
  138. {  
  139.     unregister_chrdev_region(dev,1);  
  140.   
  141.         device_destroy(led_class, dev);   
  142.         class_destroy(led_class);  
  143. }  
  144.   
  145. module_init(dev_init);  
  146. module_exit(dev_exit);  
  147. MODULE_LICENSE("GPL");  
  148. MODULE_AUTHOR("JDH");  

测试

用中的测试程序进行测试:

开启两个程序,同时打开,双进程同时操作LED

相关内容