注意事项:down(&my_leds_sem); //will always wait
down_interruptible(&my_leds_sem); //will always wait, but can be intertuptible,
the same shared driver semaphore,no matter your test procedure
内核版本:Linux 2.6.38
开发板: Mini 6410
驱动程序:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/timer.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/semaphore.h>
/*
Kernel Version: Linux 2.6.38
Arm Version: Mini 6410
*/
#define MyPrintk printk
static struct semaphore my_leds_sem;
struct my_data_structure
{
unsigned int number;
char name[20];
unsigned long count;
};
static dev_t Leds_Major ;
static char * DEVICE_NAME = "SemaphoreData";
static struct class *leds_class;
static struct my_data_structure my_own_data[] = {
{1,"Jack",0},
{2,"Tom",0},
{3,"Kobe",0},
{4,"Xiaohong",0}
};
static ssize_t data_read(struct file *file, char __user * buffer, size_t count, loff_t *pos)
{
int ret = copy_to_user(buffer,(void *)&my_own_data[1], sizeof(struct my_data_structure));
if (ret != 0){
MyPrintk("read error\n");
}
MyPrintk("read\n");
up(&my_leds_sem);
return 0;
}
static int data_open(struct file *file, struct node *nodes)
{
//down(&my_leds_sem); //will always wait
down_interruptible(&my_leds_sem); //will always wait, but can be intertuptible,the same driver semaphore,no matter your test procedure
MyPrintk("can open semphore\n");
return 0;
}
static struct file_operations s3c64XX_leds_fops = {
.owner = THIS_MODULE,
.read = data_read,
.open = data_open,
};
static int myleds_init(void)
{
sema_init(&my_leds_sem, 3);
Leds_Major = register_chrdev(Leds_Major,DEVICE_NAME , &s3c64XX_leds_fops);
if(Leds_Major < 0){
MyPrintk (KERN_EMERG "Sorry, Can not register the data trsanmission device!\n");
}
MyPrintk (KERN_EMERG " Register the data trsanmission leds device\n");
leds_class = class_create(THIS_MODULE, DEVICE_NAME);
device_create(leds_class, NULL , MKDEV(Leds_Major, 0), NULL,DEVICE_NAME);
return 0;
}
static void myleds_exit(void)
{
unregister_chrdev(Leds_Major, DEVICE_NAME);
device_destroy(leds_class, MKDEV(Leds_Major, 0));
class_destroy(leds_class);
MyPrintk (KERN_EMERG "Data transmission Linux Byebye\n");
}
module_init(myleds_init);
module_exit(myleds_exit);
MODULE_LICENSE("GPL");
测试程序
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
#include <stdlib.h>
struct my_data_structure
{
unsigned int number;
char name[20];
unsigned long count;
};
int main(int argc, char **argv)
{
int fd;
int fd2;
int fd3;
int fd4;
int fd5;
int ret;
fd = open("/dev/SemaphoreData", O_RDWR);
fd5 = open("/dev/SemaphoreData", O_RDWR);
fd2 = open("/dev/SemaphoreData", O_RDWR);
if (fd < 0){
printf("Sorry, can't open!\n");
}
struct my_data_structure my_read_data;
ret = read(fd, &my_read_data , sizeof(my_read_data));
if(ret < 0){
printf("Sorry, read1 error!\n");
}
printf("my_read_data: %u, %s, %u\n", my_read_data.number, my_read_data.name, my_read_data.count);
sleep(1);
fd3 = open("/dev/SemaphoreData", O_RDWR);
ret = read(fd2, &my_read_data , sizeof(my_read_data));
if(ret < 0){
printf("Sorry, read1 error!\n");
}
printf("my_read_data1: %u, %s, %u\n", my_read_data.number, my_read_data.name, my_read_data.count);
sleep(1);
ret = read(fd3, &my_read_data , sizeof(my_read_data));
if(ret < 0){
printf("Sorry, read1 error!\n");
}
printf("my_read_data2: %u, %s, %u\n", my_read_data.number, my_read_data.name, my_read_data.count);
sleep(1);
fd4 = open("/dev/SemaphoreData", O_RDWR);
ret = read(fd5, &my_read_data , sizeof(my_read_data));
if(ret < 0){
printf("Sorry, read1 error!\n");
}
printf("my_read_data4: %u, %s, %u\n", my_read_data.number, my_read_data.name, my_read_data.count);
sleep(1);
ret = read(fd4, &my_read_data , sizeof(my_read_data));
if(ret < 0){
printf("Sorry, read1 error!\n");
}
printf("my_read_data3: %u, %s, %u\n", my_read_data.number, my_read_data.name, my_read_data.count);
sleep(1);
sleep(1000);
return 0;
}