Linux并发控制机制

CSDN仅用于增加百度收录权重,排版未优化,日常不维护。请访问:www.hceng.cn 查看、评论。
本博文对应地址: https://hceng.cn/2017/04/05/Linux并发控制/#more
本文主要是简单记录下驱动中的并发控制。

1.并发控制


2.原子变量操作


测试代码:
{% codeblock lang:c [atomic_drv.c] https://github.com/hceng/learn/tree/master/atomic %}
#include <linux/module.h>
#include <linux/init.h>

#include <asm/atomic.h>//原子变量操作的头文件
#include <asm/bitops.h>//原子位操作的头文件

atomic_t a1 = ATOMIC_INIT(1);//定义和设置原子量;
unsigned long int a2;//操作函数传入参数的数据类型是unsigned long int;

static int test_drv_init(void)
{

//测试原子变量操作:
printk("test a1\nKERN_INFO:atomic_read(): a1 =  %d\n", a1); 

atomic_add(4, &a1);
printk("KERN_INFO:atomic_add(): a1 =  %d\n", a1); 

atomic_dec(&a1);
printk("KERN_INFO:atomic_dec(): a1 =  %d\n", a1); 

printk("KERN_INFO:atomic_dec_and_test(): judge_a1 = %d, new_a1 = %d\n",\
	atomic_dec_and_test(&a1),atomic_read(&a1));

//测试原子位操作:
set_bit(0,&a2);//设置a的0位为1;
printk("test a2\nKERN_INFO:set_bit(): a2 =  %ld\n", a2); 

printk("KERN_INFO:test_and_clear_bit(): return_a2 = %d, new_a2 = %ld\n",\
	test_and_clear_bit(0, &a2), a2);

printk("KERN_INFO:test_and_set_bit(): return_a2 = %d, new_a2 = %ld\n",\
	test_and_set_bit(0, &a2), a2);

return 0;

}

static void test_drv_exit(void)
{

}

module_init(test_drv_init);
module_exit(test_drv_exit);

MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“hceng”);
MODULE_DESCRIPTION(“Learn for atomic”);
{% endcodeblock %}


3.自旋锁


测试代码:
{% codeblock lang:c [lock_drv.c] https://github.com/hceng/learn/blob/master/lock/lock_drv.c %}
/设备驱动中,有些设备只允许打开一次,这里用count计数,lock对count进行保护/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/spinlock.h>//自旋锁头文件

static struct class *testdrv_class;
static struct class_device *testdrv_class_dev;

int count = 0 ;
spinlock_t lock;

static int test_drv_open(struct inode *inode, struct file *file)
{
spin_lock(&lock);
if(count)
{
spin_unlock(&lock);
printk(“kernel: open fail! count = %d\n”,count);
return -EBUSY;
}
count++;
spin_unlock(&lock);
printk(“kernel: open ok! count = %d\n”,count);

return 0;

}

static int test_drv_release(struct inode *inode, struct file *file)
{
spin_lock(&lock);
count–;
spin_unlock(&lock);
printk(“kernel: release ok! count = %d\n”,count);

return 0;

}

static struct file_operations test_drv_fops = {
.owner = THIS_MODULE,
.open = test_drv_open,
.release = test_drv_release,
};

int major;
static int test_drv_init(void)
{
major = register_chrdev(0, “test_drv”, &test_drv_fops);

testdrv_class = class_create(THIS_MODULE, "testdrv");

testdrv_class_dev = device_create(testdrv_class, NULL, MKDEV(major, 0), NULL, "locktest"); 

spin_lock_init(&lock);

printk("kernel: init ok!\n");

return 0;

}

static void test_drv_exit(void)
{
unregister_chrdev(major, “test_drv”);

device_destroy(testdrv_class,  MKDEV(major, 0));	

class_destroy(testdrv_class);

printk("kernel: exit ok!\n");

}

module_init(test_drv_init);
module_exit(test_drv_exit);

MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“hceng”);
MODULE_DESCRIPTION(“Learn for lock”);
{% endcodeblock %}
{% codeblock lang:c [lock_test.c] https://github.com/hceng/learn/blob/master/lock/lock_test.c %}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc, char **argv)
{
int fd;

fd = open("/dev/locktest", O_RDWR);

if (fd < 0)
{
	printf("app: can't open!\n");
}
else printf("app: open ok!\n");

while(1);

return 0;

}
{% endcodeblock %}


4.信号量


{% codeblock lang:c [semaphore_drv.c] https://github.com/hceng/learn/blob/master/semaphore/semaphore_drv.c %}
/设备驱动中,有些资源只能被单一进程访问,这里用sem确保单一访问/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/semaphore.h>//信号量头文件

static struct class *testdrv_class;
static struct class_device *testdrv_class_dev;

struct semaphore sem;

static int test_drv_open(struct inode *inode, struct file *file)
{
printk(“kernel:down before sem.count = %d \n”, sem.count);
down(&sem);
/临界资源/
printk(“kernel:down after sem.count = %d \n”, sem.count);

return 0;

}

static int test_drv_release(struct inode *inode, struct file *file)
{
printk(“kernel:up before sem.count = %d \n”, sem.count);
up(&sem);
printk(“kernel:up after sem.count = %d \n”, sem.count);

return 0;

}

static struct file_operations test_drv_fops = {
.owner = THIS_MODULE,
.open = test_drv_open,
.release = test_drv_release,
};

int major;
static int test_drv_init(void)
{
major = register_chrdev(0, “test_drv”, &test_drv_fops);

testdrv_class = class_create(THIS_MODULE, "testdrv");

testdrv_class_dev = device_create(testdrv_class, NULL, MKDEV(major, 0), NULL, "semaphoretest"); 

sema_init(&sem, 2);//允许同时2个进程访问临界资源

printk("kernel: init ok!\n");

return 0;

}

static void test_drv_exit(void)
{
unregister_chrdev(major, “test_drv”);

device_destroy(testdrv_class,  MKDEV(major, 0));	

class_destroy(testdrv_class);

printk("kernel: exit ok!\n");

}

module_init(test_drv_init);
module_exit(test_drv_exit);

MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“hceng”);
MODULE_DESCRIPTION(“Learn for semaphore”);
{% endcodeblock %}

{% codeblock lang:c [semaphore_test.c] https://github.com/hceng/learn/blob/master/semaphore/semaphore_test.c %}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc, char **argv)
{
int fd;

fd = open("/dev/semaphoretest", O_RDWR);

if (fd < 0)
{
	printf("app: can't open!\n");
}
else printf("app: open ok!\n");

while(1);

return 0;

}
{% endcodeblock %}


5.完成量

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值