招生热线
0755-86191118 0755-86191118
我的位置: 首页 > 学习专区 > .NET技术 > C语言一个简单的字符驱动程序

C语言一个简单的字符驱动程序

2013-05-25 09:02:04
来源:
[导读] 代码分为:makefile ,内核态程序 globalmem c 用户态程序 user c 功能是把一个数组排序,你也可以使用 read write函数往内存里写东
代码分为:makefile ,内核态程序 globalmem.c 用户态程序 user.c 功能是把一个数组排序,你也可以使用 read write函数往内存里写东西。

运行方法:

make,产生globalmem.ko文件, Insmod globalmem.ko , 看一下 dmesg -c 是否有提示信息(也可以 lsmod | grep "glo"), 有的话说明加载上了,

然后 mknod /dev globalmem c 254 0 , 看一下 ls /proc/device/ | grep "glo" 有东西没。

然后运行用户态程序,数组被排序了。dmesg -c 可以看到提示信息, 在模块中排序了。

上代码(是带锁的代码,顺便练练手)

makefile

1# makefile for kernel 2.6

2ifneq ($(KERNELRELEASE),)

3#mymodule-objs := file1.o file2.o

4obj-m := globalmem.o

5

6else

7PWD := $(shell pwd)

8KVER := $(shell uname -r)

9KDIR := /lib/modules/$(KVER)/build

10all:

11 $(MAKE) -C $(KDIR) M=$(PWD)

12clean:

13 rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions

14

15endif

16

内核模块

1#include

2#include

3#include

4#include

5#include

6#include

7#include

8#include

9#include

10#include

11#include "mem.h"

12

13#define GLOBALMEM_SIZE 0x1000

14#define MEM_CLEAR 0x1

15#define ARRAY_INSTER 0x2

16#define GLOBALMEM_MAJOR 254

17

18static int globalmem_major = GLOBALMEM_MAJOR;

19

20//the struct of global

21typedef struct __globalmem_dev{

22 struct cdev cdev;

23 unsigned char mem[GLOBALMEM_SIZE];

24 //add lock, signal

25 struct semaphore sem;

26 atomic_t ato;

27}globalmem_dev;

28

29globalmem_dev * global;

30

31typedef struct __arithmetic_st{

32 int buf[10];

33 int len;

34}arithmetic_st;

35

36

37

38

39int globalmem_open(struct inode *inode, struct file * filp)

40{

41 filp->private_data = global;

42 //you can only open one file

43 if(!atomic_dec_and_test(&global->ato))

44 {

45 printk( KERN_NOTICE "atomic is lock ");

46 return -EBUSY;

47 }

48 return 0;

49}

50

51int globalmem_release(struct inode * inode, struct file * filp)

52{

53 atomic_inc(&global->ato);

54 return 0;

55}

56

57

58//read

59static ssize_t globalmem_read(struct file * filp, char __user *buf, size_t size, loff_t *ppos)

60{

61 unsigned long p = *ppos;

62 unsigned int count = size;

63 int ret = 0;

64

65 globalmem_dev *dev = filp->private_data;

66

67 if(p > GLOBALMEM_SIZE)

68 return count ? -ENXIO : 0;

69 if(count > GLOBALMEM_SIZE - p)

70 count = GLOBALMEM_SIZE - p;

71//add the lock

72 if(down_interruptible(&dev->sem))

73 {

74 return -ERESTARTSYS;

75 }

76

77

78 if(copy_to_user(buf, (void *)(dev->mem + p), count)){

79 ret = -EFAULT;

80 }else{

81 *ppos += count;

82 ret = count;

83 printk(KERN_INFO "read %d bytes from %u ", count, p);

84 }

85//unlock

86 up(&dev->sem);

87 return ret;

88}

89

90//write

91static ssize_t globalmem_write(struct file * filp, const char __user * buf,

92 size_t size, loff_t *ppos)

93{

94 unsigned long p = *ppos;

95 unsigned int count = size;

96 int ret = 0;

97 globalmem_dev *dev = filp->private_data;

98

99 if(p >= GLOBALMEM_SIZE)

100 return count ? -ENXIO : 0;

101 if(count > GLOBALMEM_SIZE - p)

102 count = GLOBALMEM_SIZE - p;

103//lock

104 if(down_interruptible(&dev->sem)){

105 return -ERESTARTSYS;

106 }

107 if(copy_from_user((dev->mem + p), buf, count))

108 ret = -EFAULT;

109 else{

110 *ppos += count;

111 ret = count;

112 printk( KERN_INFO "written %d bytes from %u ", count , p);

113 }

114//unlock

115 up(&dev->sem);

116 return ret;

117}

118

119//seek

120static loff_t globalmem_llseek(struct file * filp, loff_t offset, int orig)

121{

122 loff_t ret = 0;

123 switch(orig){

124 case 0:

125 if(offset < 0){

126 ret = -EINVAL;

127 break;

128 }

129 if((unsigned int) offset > GLOBALMEM_SIZE){

130 ret = -EINVAL;

131 break;

132 }

133 filp->f_pos = (unsigned int)offset;

134 ret = filp->f_pos;

135 break;

136 case 1:

137 if((filp->f_pos + offset) > GLOBALMEM_SIZE){

138 ret = -EINVAL;

139 break;

140 }

141 if((filp->f_pos + offset) < 0){

142 ret = -EINVAL;

143 break;

144 }

145 filp->f_pos += offset;

146 ret = filp->f_pos;

147 break;

148 default :

149 ret = -EINVAL;

150 break;

151 }

152 return ret;

153}

154static int inster_arithmetic(int * buf, int len)

155{

156 int i;

157 int j;

158 int key;

159

160 if(len < 2){

161 return -1;

162 }

163 for( j = 1; j < len; j++){

164 key = *(buf + j);

165 i = j -1;

166

167 while(i >= 0 && *(buf + i) > key){

168 *(buf + i + 1) = *(buf + i);

169 i = i - 1;

170 }

171 *(buf + i + 1) = key;

172 }

173}

174

175//ioctl

176static int globalmem_ioctl(struct inode * inode, struct file * filp,

177 unsigned int cmd, unsigned long arg)

178{

179 globalmem_dev * dev = filp->private_data;

180 arithmetic_st * p;

181 arithmetic_st * q;

182 int i;

183

184 switch(cmd){

185 case MEM_CLEAR:

186 //lock

187 if(down_interruptible(&dev->sem)){

188 return -ERESTARTSYS;

189 }

190 memset(dev->mem, 0, GLOBALMEM_SIZE);

191 printk(KERN_INFO "glbalmem is set to zero ! ");

192 //unlock

193 up(&dev->sem);

194 break;

195 case ARRAY_INSTER:

196 p = (arithmetic_st *)arg;

197 q = (arithmetic_st *)kmalloc(sizeof(arithmetic_st), GFP_KERNEL);

198 memset(q->buf, 0, 10);

199 if(down_interruptible(&dev->sem)){

200 return -ERESTARTSYS;

201 }

202 if(copy_from_user(q, p, sizeof(arithmetic_st))){

203 return -EFAULT;

204 }

205 if(q->len != 0){

206 inster_arithmetic(q->buf, q->len);

207 if(copy_to_user(p, q, sizeof(arithmetic_st))){

208 return -EFAULT;

209 }

210 for(i = 0; i < q->len; i++){

211 printk(KERN_INFO ">>>>>>>>>>buf%d:%d ! ",i, q->buf[i]);

212 }

213 }else{

214 printk(KERN_INFO ">>>>>>>>>>len is zero [%d] [%s] ! ", __LINE__, __FUNCTION__);

215 }

216 kfree(q);

217 break;

218

219 default:

220 return -EINVAL;

221 }

222 return 0;

223}

224

225static const struct file_operations globalmem_fops =

226{

227 .owner = THIS_MODULE,

228 .llseek = globalmem_llseek,

229 .read = globalmem_read,

230 .write = globalmem_write,

231 .ioctl = globalmem_ioctl,

232 .open = globalmem_open,

233 .release = globalmem_release,

234};

235//register cdev

236static void globalmem_setup_cdev(globalmem_dev * dev, int index)

237{

238 int err;

239 int devno = MKDEV(globalmem_major, index);

240

241 cdev_init(&dev->cdev, &globalmem_fops);

242 dev->cdev.owner = THIS_MODULE;

243// dev->cdev.ops = &globalmem_fops;

244 err = cdev_add(&dev->cdev, devno, 1);

245 if(err)

246 printk( KERN_NOTICE "error %d adding LED %d" , err, index);

247}

248

249//

250int globalmem_init(void)

251{

252 int result;

253 dev_t devno = MKDEV(globalmem_major, 0);

254

255 if(globalmem_major){

256 result = register_chrdev_region(devno, 1, "globalmem");

257 }else{

258 result = alloc_chrdev_region(&devno, 0, 1, "globalmem");

259 globalmem_major = MAJOR(devno);

260 }

261 if(result < 0)

262 return result;

263 global = kmalloc(sizeof(globalmem_dev), GFP_KERNEL);

264 if(!global){

265 result = -ENOMEM;

266 goto fail_kmalloc;

267 }

268 memset(global, 0, sizeof(globalmem_dev));

269 globalmem_setup_cdev(global, 0);

270 printk( KERN_NOTICE "init over! ");

271 //lock

272 init_MUTEX(&global->sem);

273 atomic_set(&global->ato, 1);

274 printk( KERN_NOTICE "init signl! ");

275 printk( KERN_INFO "the process is %s pid is %i ", current->comm, current->pid);

276 return 0;

277

278fail_kmalloc:

279 unregister_chrdev_region(devno, 1);

280 return result;

281}

282//

283void globalmem_exit(void)

284{

285 cdev_del(&global->cdev);

286 kfree(global);

287 unregister_chrdev_region(MKDEV(globalmem_major, 0), 1);

288 printk( KERN_NOTICE "exit over! ");

289}

290

291MODULE_AUTHOR("xueby");

292MODULE_LICENSE("XBY/GPL");

293module_param(globalmem_major, int , S_IRUGO);

294

295module_init(globalmem_init);

296module_exit(globalmem_exit);

深圳北大青鸟

评论