環境:
主機: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]
- #include <linux/miscdevice.h>
- #include <linux/delay.h>
- #include <asm/irq.h>
- //#include <mach/regs-gpio.h>
- #include <mach/hardware.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/mm.h>
- #include <linux/fs.h>
- #include <linux/types.h>
- #include <linux/delay.h>
- #include <linux/moduleparam.h>
- #include <linux/slab.h>
- #include <linux/errno.h>
- #include <linux/ioctl.h>
- #include <linux/cdev.h>
- #include <linux/string.h>
- #include <linux/list.h>
- #include <linux/pci.h>
- #include <asm/uaccess.h>
- #include <asm/atomic.h>
- #include <asm/unistd.h>
- #include <linux/major.h>
-
- #include <mach/map.h>
- #include <mach/regs-clock.h>
- #include <mach/regs-gpio.h>
-
- #include <plat/gpio-cfg.h>
- #include <mach/gpio-bank-e.h>
- #include <mach/gpio-bank-k.h>
- #include <mach/gpio-bank-h.h>
- #include <mach/gpio-bank-n.h>
- #include <mach/gpio-bank-l.h>
- #include <mach/gpio-bank-p.h>
-
- #include <linux/device.h>
-
- #include <linux/jiffies.h>
-
- #define DEVICE_NAME "led_driver"
- #define T_MAJORS 700
-
- static struct cdev fun_cdev;
- static dev_t dev;
- static struct class *led_class;
-
- struct semaphore sem;
-
- //功能:初始化IO
- static void init_led(void)
- {
- unsigned temp;
-
- //GPK4-7設置為輸出
- temp = readl(S3C64XX_GPKCON);
- temp &= ~((0xf << 4) | (0xf << 5) | (0xf << 6) | (0xf<< 7));
- temp |= (1 << 16) | (1 << 20) | (1 << 24) | (1 << 28);
- writel(temp, S3C64XX_GPKCON);
- }
-
- //功能:ioctl操作函數
- //返回值:成功返回0
- static long led_driver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- {
- unsigned int temp = 0;
- //unsigned long t = 0;
- wait_queue_head_t wait;
-
- //獲取信號量
- if (down_interruptible(&sem))
- {
- return -1;
- }
-
- temp = readl(S3C64XX_GPKDAT);
- if (cmd == 0)
- {
- temp &= ~(1 << (arg + 3));
- }
- else
- {
- temp |= 1 << (arg + 3);
- }
-
- //等待2S
- //t = jiffies;
- //while (time_after(jiffies,t + 2 * HZ) != 1);
- init_waitqueue_head(&wait);
- sleep_on_timeout(&wait,2 * HZ);
- writel(temp,S3C64XX_GPKDAT);
-
- printk (DEVICE_NAME"\tjdh:led_driver cmd=%d arg=%d jiffies = %d\n",cmd,arg,jiffies);
-
- //釋放信號量
- up(&sem);
-
- return 0;
- }
-
- static struct file_operations io_dev_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = led_driver_ioctl,
- };
-
- static int __init dev_init(void)
- {
- int ret;
- unsigned temp;
-
- init_led();
-
- dev = MKDEV(T_MAJORS,0);
- cdev_init(&fun_cdev,&io_dev_fops);
- ret = register_chrdev_region(dev,1,DEVICE_NAME);
- if (ret < 0) return 0;
- ret = cdev_add(&fun_cdev,dev,1);
- if (ret < 0) return 0;
-
- printk (DEVICE_NAME"\tjdh:led_driver initialized!!\n");
-
- led_class = class_create(THIS_MODULE, "led_class1");
- if (IS_ERR(led_class))
- {
- printk(KERN_INFO "create class error\n");
- return -1;
- }
- device_create(led_class, NULL, dev, NULL, "led_driver");
-
- //初始化信號量
- sema_init(&sem,1);
-
- return ret;
- }
-
- static void __exit dev_exit(void)
- {
- unregister_chrdev_region(dev,1);
-
- device_destroy(led_class, dev);
- class_destroy(led_class);
- }
-
- module_init(dev_init);
- module_exit(dev_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("JDH");
測試
用http://www.linuxidc.com/Linux/2012-01/51818.htm中的測試程序進行測試:
開啟兩個程序,同時打開,雙進程同時操作LED