linux实验 进程同步与互斥_正点原子Linux第四十八章Linux并发与竞争实验

1)资料下载:点击资料即可下载

2)对正点原子Linux感兴趣的同学可以加群讨论:935446741

3)关注正点原子公众号,获取最新资料更新

45380d2803211217e8a5e86f2b61af1d.png

第四十八章Linux并发与竞争实验

在上一章中我们学习了Linux下的并发与竞争,并且学习了四种常用的处理并发和竞争的机制:原子操作、自旋锁、信号量和互斥体。本章我们就通过四个实验来学习如何在驱动中使用这四种机制。

48.1 原子操作实验

本实验对应的例程路径为:开发板光盘->2、Linux驱动例程->7_atomic。

本例程我们在第四十五章的gpioled.c文件基础上完成。在本节使用中我们使用原子操作来实现对LED这个设备的互斥访问,也就是一次只允许一个应用程序可以使用LED灯。

48.1.1 实验程序编写

1、修改设备树文件

因为本章实验是在第四十五章实验的基础上完成的,因此不需要对设备树做任何的修改。

2、LED驱动修改

本节实验在第四十五章实验驱动文件gpioled.c的基础上修改而来。新建名为“7_atomic”的文件夹,然后在7_atomic文件夹里面创建vscode工程,工作区命名为“atomic”。将5_gpioled实验中的gpioled.c复制到7_atomic文件夹中,并且重命名为atomic.c。本节实验重点就是使用atomic来实现一次只能允许一个应用访问LED,所以我们只需要在atomic.c文件源码的基础上加上添加atomic相关代码即可,完成以后的atomic.c文件内容如下所示:

示例代码48.1.1.1 atomic.c文件代码段

1 #include <linux/types.h>

2 #include <linux/kernel.h>

3 #include <linux/delay.h>

4 #include <linux/ide.h>

5 #include <linux/init.h>

6 #include <linux/module.h>

7 #include <linux/errno.h>

8 #include <linux/gpio.h>

9 #include <linux/cdev.h>

10 #include <linux/device.h>

11 #include <linux/of.h>

12 #include <linux/of_address.h>

13 #include <linux/of_gpio.h>

14 #include <asm/mach/map.h>

15 #include <asm/uaccess.h>

16 #include <asm/io.h>

17/***************************************************************

18 Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.

19文件名 : atomic.c

20作者 : 左忠凯

21版本 : V1.0

22描述 : 原子操作实验,使用原子变量来实现对实现设备的互斥访问

23其他 : 无

24论坛 : http://www.openedv.com

25日志 : 初版V1.0 2019/7/18 左忠凯创建

26 ***************************************************************/

27 #define GPIOLED_CNT 1 /* 设备号个数 */

28 #define GPIOLED_NAME "gpioled" /* 名字 */

29 #define LEDOFF 0 /* 关灯 */

30 #define LEDON 1 /* 开灯 */

31

32/* gpioled设备结构体 */

33struct gpioled_dev{

34 dev_t devid; /* 设备号 */

35struct cdev cdev; /* cdev */

36struct class *class; /* 类 */

37struct device *device; /* 设备 */

38int major; /* 主设备号 */

39int minor; /* 次设备号 */

40struct device_node *nd; /* 设备节点 */

41int led_gpio; /* led所使用的GPIO编号 */

42 atomic_t lock; /* 原子变量 */

43};

44

45struct gpioled_dev gpioled;/* led设备 */

46

47/*

48 * @description : 打开设备

49 * @param – inode : 传递给驱动的inode

50 * @param - filp : 设备文件,file结构体有个叫做private_data的成员变量

51 * 一般在open的时候将private_data指向设备结构体。

52 * @return : 0 成功;其他失败

53 */

54staticint led_open(struct inode *inode,struct file *filp)

55{

56/* 通过判断原子变量的值来检查LED有没有被别的应用使用 */

57if(!atomic_dec_and_test(&gpioled.lock)){

58 atomic_inc(&gpioled.lock);/* 小于0的话就加1,使其原子变量等于0 */

59return-EBUSY;/* LED被使用,返回忙 */

60}

61

62 filp->private_data =&gpioled;/* 设置私有数据 */

63return0;

64}

65

66/*

67 * @description : 从设备读取数据

68 * @param - filp : 要打开的设备文件(文件描述符)

69 * @param - buf : 返回给用户空间的数据缓冲区

70 * @param – cnt : 要读取的数据长度

71 * @param - offt : 相对于文件首地址的偏移

72 * @return : 读取的字节数,如果为负值,表示读取失败

73 */

74static ssize_t led_read(struct file *filp,char __user *buf,

size_t cnt, loff_t *offt)

75{

76return0;

77}

78

79/*

80 * @description : 向设备写数据

81 * @param – filp : 设备文件,表示打开的文件描述符

82 * @param - buf : 要写给设备写入的数据

83 * @param - cnt : 要写入的数据长度

84 * @param – offt : 相对于文件首地址的偏移

85 * @return : 写入的字节数,如果为负值,表示写入失败

86 */

87static ssize_t led_write(struct file *filp,constchar __user *buf,

size_t cnt, loff_t *offt)

88{

89int retvalue;

90unsignedchar databuf[1];

91unsignedchar ledstat;

92struct gpioled_dev *dev = filp->private_data;

93

94 retvalue = copy_from_user(databuf, buf, cnt);

95if(retvalue <0){

96 printk("kernel write failed!rn");

97return-EFAULT;

98}

99

100 ledstat = databuf[0]; /* 获取状态值 */

101

102if(ledstat == LEDON){

103 gpio_set_value(dev->led_gpio,0);/* 打开LED灯 */

104}elseif(ledstat == LEDOFF){

105 gpio_set_value(dev->led_gpio,1);/* 关闭LED灯 */

106}

107return0;

108}

109

110/*

111 * @description : 关闭/释放设备

112 * @param – filp : 要关闭的设备文件(文件描述符)

113 * @return : 0 成功;其他失败

114 */

115staticint led_release(struct inode *inode,struct file *filp)

116{

117struct gpioled_dev *dev = filp->private_data;

118

119/* 关闭驱动文件的时候释放原子变量 */

120 atomic_inc(&dev->lock);

121return0;

122}

123

124/* 设备操作函数 */

125staticstruct file_operations gpioled_fops ={

126.owner = THIS_MODULE,

127.open = led_open,

128.read = led_read,

129.write = led_write,

130.release = led_release,

131};

132

133/*

134 * @description : 驱动入口函数

135 * @param : 无

136 * @return : 无

137 */

138staticint __init led_init(void)

139{

140int ret =0;

141

142/* 初始化原子变量 */

143 atomic_set(&gpioled.lock,1);/* 原子变量初始值为1 */

144

145/* 设置LED所使用的GPIO */

146/* 1、获取设备节点:gpioled */

147 gpioled.nd = of_find_node_by_path("/gpioled");

148if(gpioled.nd ==NULL){

149 printk("gpioled node not find!rn");

150return-EINVAL;

151}else{

152 printk("gpioled node find!rn");

153}

154

155/* 2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值