实例一:没有信号量的程序
1、 nosem\driver\ nosem.c驱动源代码
#include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/init.h> #include <linux/serio.h> #include <linux/delay.h> #include <linux/clk.h> #include <linux/miscdevice.h> #include <linux/gpio.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <mach/regs-clock.h> #include <plat/regs-timer.h> #include <mach/regs-gpio.h> #include <linux/cdev.h> static int test_major = 0; MODULE_AUTHOR("Hanson He"); MODULE_LICENSE("Dual BSD/GPL"); #define GLOBALMEM_SIZE 0x1000 /*全局内存最大4K字节*/ unsigned char mem[GLOBALMEM_SIZE]; /*全局内存*/ /* * Open the device; in fact, there's nothing to do here. */ int test_open (struct inode *inode, struct file *filp) { return 0; } ssize_t test_read(struct file *file, char __user *buff, size_t count, loff_t *offp) { return 0; } ssize_t test_write(struct file *file, const char __user *buff, size_t count, loff_t *offp) { int i; unsigned long p = *offp; int ret = 0; /*分析和获取有效的写长度*/ if (p >= GLOBALMEM_SIZE) return count ? - ENXIO: 0; if (count > GLOBALMEM_SIZE - p) count = GLOBALMEM_SIZE - p; /*用户空间->内核空间*/ if (copy_from_user(mem + p, buff, count)) ret = - EFAULT; else { *offp += count; ret = count; //printk(KERN_INFO "written %d bytes(s) from %d\n", count, p); } for(i=0;i<count;i++) { printk("%d",mem[i]); msleep(100); //delay 1ms } printk("\n"); return 0; } static int test_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { return 0; } static int test_release(struct inode *node, struct file *file) { return 0; } /* * Set up the cdev structure for a device. */ static void test_setup_cdev(struct cdev *dev, int minor, struct file_operations *fops) { int err, devno = MKDEV(test_major, minor); cdev_init(dev, fops); dev->owner = THIS_MODULE; dev->ops = fops; err = cdev_add (dev, devno, 1); /* Fail gracefully if need be */ if (err) printk (KERN_NOTICE "Error %d adding test%d", err, minor); } /* * Our various sub-devices. */ /* Device 0 uses remap_pfn_range */ static struct file_operations test_remap_ops = { .owner = THIS_MODULE, .open = test_open, .release = test_release, .read = test_read, .write = test_write, .ioctl = test_ioctl, }; /* * There's no need for us to maintain any * special housekeeping info, so we just deal with raw cdevs. */ static struct cdev TestDevs; /* * Module housekeeping. */ static int test_init(void) { int result; dev_t dev = MKDEV(test_major, 0); /* Figure out our device number. */ if (test_major) result = register_chrdev_region(dev, 1, "nosem"); else { result = alloc_chrdev_region(&dev, 0, 1, "nosem"); test_major = MAJOR(dev); } if (result < 0) { printk(KERN_WARNING "test: unable to get major %d\n", test_major); return result; } if (test_major == 0) test_major = result; /* Now set up cdev. */ test_setup_cdev(&TestDevs, 0, &test_remap_ops); printk("test device installed, with major %d\n", test_major); return 0; } static void test_cleanup(void) { cdev_del(&TestDevs); unregister_chrdev_region(MKDEV(test_major, 0), 1); printk("test device uninstalled\n"); } module_init(test_init); module_exit(test_cleanup);
2、 Mafefile文件
ifeq ($(KERNELRELEASE),) #KERNELDIR ?= /your/target/source/directory/ KERNELDIR ?=/home/student/linux-2.6.32.2 PWD := $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions .PHONY: modules modules_install clean else obj-m := nosem.o endif
3、 nosem\user\ main.c测试程序
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> int main(int argc, char *argv[]) { int i = 0; int dev_fd; char wr_buf[60]; int cnt = 0; int input = 0; if(argc > 1) { input = atoi(argv[1]); }else{ printf("usage: nosem_test number\n"); exit(1); } dev_fd = open("/dev/nosem",O_RDWR); if ( dev_fd == -1 ) { printf("Can't open file /dev/nosem\n"); exit(1); } memset(wr_buf, input, sizeof(wr_buf)); /*print out 100 line number, there are 60 one every line*/ while(1) { lseek(dev_fd,0,SEEK_SET); write(dev_fd,wr_buf,sizeof(wr_buf)); cnt ++; if(cnt > 100)break; usleep(8); } close(dev_fd); return 0; }
4、 Makefile文件
KERNELDIR ?=/home/student/linux-2.6.32.2/include all: nosem_test nosem_test : main.c #arm-linux-gcc -I$(KERNELDIR) -s -Wl,-warn-common --static -o $@ $^ arm-linux-gcc -I$(KERNELDIR) -o $@ $^ clean : rm nosem_test
5、run_nosemtests多个测试
./nosem_test 1 &
./nosem_test 2 &
./nosem_test 3 &
实例二:带信号量的程序
6、 \sem\driver\ Sem.c驱动源代码
#include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/init.h> #include <linux/serio.h> #include <linux/delay.h> #include <linux/clk.h> #include <linux/miscdevice.h> #include <linux/gpio.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <mach/regs-clock.h> #include <plat/regs-timer.h> #include <mach/regs-gpio.h> #include <linux/cdev.h> DECLARE_MUTEX(sem); //声明一个互斥体 static int test_major = 0; MODULE_AUTHOR("Hanson He"); MODULE_LICENSE("Dual BSD/GPL"); #define GLOBALMEM_SIZE 0x1000 /*全局内存最大4K字节*/ unsigned char mem[GLOBALMEM_SIZE]; /*全局内存*/ /* * Open the device; in fact, there's nothing to do here. */ int test_open (struct inode *inode, struct file *filp) { return 0; } ssize_t test_read(struct file *file, char __user *buff, size_t count, loff_t *offp) { return 0; } ssize_t test_write(struct file *file, const char __user *buff, size_t count, loff_t *offp) { int i; unsigned long p = *offp; int ret = 0; /*分析和获取有效的写长度*/ if (p >= GLOBALMEM_SIZE) return count ? - ENXIO: 0; if (count > GLOBALMEM_SIZE - p) count = GLOBALMEM_SIZE - p; if(down_interruptible(&sem)) { return -ERESTARTSYS; } /*用户空间->内核空间 以下是临界区*/ if (copy_from_user(mem + p, buff, count)) ret = - EFAULT; else { *offp += count; ret = count; //printk(KERN_INFO "written %d bytes(s) from %d\n", count, p); } for(i=0;i<count;i++) { printk("%d",mem[i]); msleep(1); //delay 1ms } printk("\n"); up(&sem); return 0; } static int test_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { return 0; } static int test_release(struct inode *node, struct file *file) { return 0; } /* * Set up the cdev structure for a device. */ static void test_setup_cdev(struct cdev *dev, int minor, struct file_operations *fops) { int err, devno = MKDEV(test_major, minor); cdev_init(dev, fops); dev->owner = THIS_MODULE; dev->ops = fops; err = cdev_add (dev, devno, 1); /* Fail gracefully if need be */ if (err) printk (KERN_NOTICE "Error %d adding test%d", err, minor); } /* * Our various sub-devices. */ /* Device 0 uses remap_pfn_range */ static struct file_operations test_remap_ops = { .owner = THIS_MODULE, .open = test_open, .release = test_release, .read = test_read, .write = test_write, .ioctl = test_ioctl, }; /* * There's no need for us to maintain any * special housekeeping info, so we just deal with raw cdevs. */ static struct cdev TestDevs; /* * Module housekeeping. */ static int test_init(void) { int result; dev_t dev = MKDEV(test_major, 0); char dev_name[]="sem"; /* Figure out our device number. */ if (test_major) result = register_chrdev_region(dev, 1, dev_name); else { result = alloc_chrdev_region(&dev, 0, 1, dev_name); test_major = MAJOR(dev); } if (result < 0) { printk(KERN_WARNING "test: unable to get major %d\n", test_major); return result; } if (test_major == 0) test_major = result; /* Now set up cdev. */ test_setup_cdev(&TestDevs, 0, &test_remap_ops); printk("test device installed, with major %d\n", test_major); printk("The device name is: %s\n", dev_name); return 0; } static void test_cleanup(void) { cdev_del(&TestDevs); unregister_chrdev_region(MKDEV(test_major, 0), 1); printk("test device uninstalled\n"); } module_init(test_init); module_exit(test_cleanup);
7、 Mafefile文件 ifeq ($(KERNELRELEASE),) #KERNELDIR ?= /your/target/source/directory/ KERNELDIR ?=/home/student/linux-2.6.32.2 PWD := $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions .PHONY: modules modules_install clean else obj-m := sem.o endif
8、 sem\use\ Main.c测试程序 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> int main(int argc, char *argv[]) { int i = 0; int dev_fd; char wr_buf[60]; int cnt = 0; int input = 0; if(argc > 1) { input = atoi(argv[1]); }else{ printf("usage: sem_test num\n"); exit(1); } dev_fd = open("/dev/sem",O_RDWR); if ( dev_fd == -1 ) { printf("Cann't open file /dev/sem\n"); exit(1); } memset(wr_buf, input, sizeof(wr_buf)); /*print out 100 line input, there are 60 one every line*/ while(1) { lseek(dev_fd, 0, SEEK_SET); write(dev_fd,wr_buf,sizeof(wr_buf)); cnt ++; if(cnt > 100)break; usleep(8); } close(dev_fd); return 0; }
9、 Makefile
KERNELDIR ?=/home/student/linux-2.6.32.2/include
all: sem_test
sem_test : main.c
#arm-linux-gcc -I$(KERNELDIR) -s -Wl,-warn-common --static -o $@ $^
arm-linux-gcc -I$(KERNELDIR) -o $@ $^
clean :
10、run_semtests多个测试
./sem_test 1 &
./sem_test 2 &
./sem_test 3 &
声明:本文非原创,整理自申嵌
3-2信号量驱动实例
最新推荐文章于 2023-04-19 10:56:39 发布