您的位置:首页 > 运维架构 > Linux

Linux驱动:信号量同步测试

2012-01-05 19:02 204 查看
Linux驱动:信号量同步测试

本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.

环境:

主机: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);

测试代码:

#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");


测试
/article/1414695.html中的测试程序进行测试:

开启两个程序,同时打开,双进程同时操作LED
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: