DOWN操作:linux内核。信号DOWN例如,下面的操作:

  • void down(struct semaphore *sem); //不间断
  • int down_interruptible(struct semaphore *sem);//可中断
  • int down_killable(struct semaphore *sem);//睡眠的进程能够由于受到致命信号而被唤醒,中断获取信号量的操作。

  • int down_trylock(struct semaphore *sem);//试图获取信号量,若无法获得则直接返回1而不睡眠。

    返回0则 表示获取到了信号量

  • int down_timeout(struct semaphore *sem,long jiffies);//表示睡眠时间是有限制的。假设在jiffies指明的时间到期时仍然无法获得信号量,则将返回错误码。

在以上四种函数中,驱动程序使用的最频繁的就是down_interruptible函数,下面将对该函数进行分析。

down_interruptible函数的定义例如以下:

int down_interruptible(struct semaphore *sem)
{
unsigned long flags;
int result = 0;
spin_lock_irqsave(&sem->lock,flags);
if (likely(sem->count> 0))
sem->count--;
else
result =__down_interruptible(sem);
spin_unlock_irqrestore(&sem->lock,flags);
return result;
}

函数分析:函数首先通过spin_lock_irqsave的调用来保证对sem->count操作的原子性。假设count>0。表示当前进程能够获得信号量,将count的值减1然后退出。

假设count不大于0,表明当前进程无法获取信号量,则调用__down_interruptible,后者会继续调用__down_common。

__down_common 函数定义例如以下:

static inline int __sched __down_common(struct semaphore *sem, longstate,
longtimeout)
{
struct task_struct *task= current;
struct semaphore_waiterwaiter;
list_add_tail(&waiter.list,&sem->wait_list);
waiter.task = task;
waiter.up = 0;
for (;;) {
if(signal_pending_state(state, task))
gotointerrupted;
if (timeout <=0)
gototimed_out;
__set_task_state(task,state);
spin_unlock_irq(&sem->lock);
timeout =schedule_timeout(timeout);
spin_lock_irq(&sem->lock);
if (waiter.up)
return 0;
}
timed_out:
list_del(&waiter.list);
return -ETIME;
interrupted:
list_del(&waiter.list);
return -EINTR;
}

函数分析:在__down_common函数数运行了下面操作。

(1)将当前进程放到信号量成员变量wait_list所管理的队列中。

(2)在一个for循环中把当前的进程状态这是为TASK_INTERRUPTIBLE,在调用schedule_timeout使当前进程进入睡眠状态。函数将停留在schedule_timeout调用上,知道再次被调度运行。

(3) 当该进程再一次被调度时,按原因运行对应的操作:假设waiter.up不为0说明进程被该信号量的up操作所唤醒,进程能够获得信号量。假设进程是由于被用户空间的信号所中断或超时信号所引起的唤醒。则返回对应的错误代码。

UP操作:LINUX内核仅仅提供了一个up函数

up函数定义例如以下:

void up(struct semaphore *sem)
{
unsigned long flags; spin_lock_irqsave(&sem->lock,flags);
if(likely(list_empty(&sem->wait_list)))
sem->count++;
else
__up(sem);
spin_unlock_irqrestore(&sem->lock,flags);
}

函数分析:假设sem的wait_list队列为空,则表明没有其它进程正在等待该信号量,那么仅仅须要把sem的count加1就可以。假设wait_list队列不为空,则说明有其它进程正睡眠在wait_list上等待该信号。此时调用__up(sem)来唤醒进程:

__up()函数定义例如以下:

static noinline void __sched __up(struct semaphore *sem)
{
struct semaphore_waiter*waiter = list_first_entry(&sem->wait_list,
structsemaphore_waiter, list);
list_del(&waiter->list);
waiter->up = 1;
wake_up_process(waiter->task);
}

函数分析:在函数中,调用了wake_up_process来唤醒进程,这样进程就从之前的__down_interruptible调用中的timeout=schedule_timeout(timeout)处醒来,wait-up=1, __down_interruptible返回0。进程获得了信号量。

up()与down()函数之间的联系:由上面对两个函数的分析能够知道,__down_common函数中timeout=schedule_timeout(timeout) 它具有非常重要的数据。

版权声明:本文博主原创文章,博客,未经同意不得转载。

信号量机制DOWN操作和UP操作的详细说明的更多相关文章

  1. 【转】进程同步之信号量机制(pv操作)及三个经典同步问题

    原文地址:http://blog.csdn.net/speedme/article/details/17597373 上篇博客中(进程同步之临界区域问题及Peterson算法),我们对临界区,临界资源 ...

  2. 锁机制(Lock) 信号量机制(Semaphore) 事件机制(Event)

    IPC  进程间通信(inter-Process Communicate) 锁机制(Lock) l = Lock() 开启一个锁机制(实例化)   一把锁配一个钥匙 l.acquire()  获得钥匙 ...

  3. Linux高级调试与优化——信号量机制与应用程序崩溃

    背景介绍 Linux分为内核态和用户态,用户态通过系统调用(syscall)进入内核态执行. 用户空间的glibc库将Linux内核系统调用封装成GNU C Library库文件(兼容ANSI &am ...

  4. RapidIO 逻辑层IO操作与Message操作的原理和区别

    接上一篇 SRIO RapidIO (SRIO)协议介绍(一) 1     说明 查看协议手册时会发现,逻辑层的操作分成了IO和Message 2类动作,那么为什么要分成2类操作?从原理和应用角度来看 ...

  5. Python之路-(Django(csrf,中间件,缓存,信号,Model操作,Form操作))

    csrf 中间件 缓存 信号 Model操作 Form操作 csrf: 用 django 有多久,我跟 csrf 这个概念打交道就有久了. 每次初始化一个项目时都能看到 django.middlewa ...

  6. python基础操作以及hdfs操作

    目录 前言 基础操作 hdfs操作 总结 一.前言        作为一个全栈工程师,必须要熟练掌握各种语言...HelloWorld.最近就被"逼着"走向了python开发之路, ...

  7. [WCF编程]10.操作:单向操作

    一.单向操作概述 WCF提供了单向操作,一旦客户端调用,WCF会生成一个请求,但没有相关的应答信息返回给客户端.所以,单向操作是不能有返回值,服务抛出的任何异常都不会传递给客户端. 理想情况下,一旦客 ...

  8. Linq查询操作之聚合操作(count,max,min,sum,average,aggregate,longcount)

    在Linq中有一些这样的操作,根据集合计算某一单一值,比如集合的最大值,最小值,平均值等等.Linq中包含7种操作,这7种操作被称作聚合操作. 1.Count操作,计算序列中元素的个数,或者计算满足一 ...

  9. Linq查询操作之排序操作

    在Linq中排序操作可以按照一个或多个关键字对序列进行排序.其中第一个排序关键字为主要关键字,第二个排序关键字为次要关键字.Linq排序操作共包含以下5个基本的操作. 1.OrderBy操作,根据排序 ...

  10. Linq查询操作之投影操作

    投影操作,乍一看不知道在说啥.那么什么是投影操作呢?其实就是Select操作,名字起的怪怪的.和Linq查询表达式中的select操作是一样的.它能够选择数据源中的元素,并指定元素的表现形式.投影操作 ...

随机推荐

  1. hdu3790最短路径问题

    题意是这种,给你一个无向图, 每条边有距离和花费, 假设从第一个点到末点的最短路不唯一, 则输出最短路长度以及最少的花费. 否则输出长度和花费即可. 用传说中的链式向前星优化了一下边的存储, 写了个s ...

  2. poj 3237 Tree(树链拆分)

    题目链接:poj 3237 Tree 题目大意:给定一棵树,三种操作: CHANGE i v:将i节点权值变为v NEGATE a b:将ab路径上全部节点的权值变为相反数 QUERY a b:查询a ...

  3. 站点系统压力測试Jmeter+Badboy

    近期项目须要压力測试,因此搜了几款试用,首选的是LoadRunner这款大名鼎鼎的測试软件: LoadRunner11 下载请猛戳这里 传送门LoadRunner破解文件 下载请猛戳这里 传送门Loa ...

  4. SQL SERVER中XML查询:FOR XML指定PATH

    SQL SERVER中XML查询:FOR XML指定PATH 前言 在SQL SERVER中,XML查询能够指定RAW,AUTO,EXPLICIT,PATH.本文用一些实例介绍SQL SERVER中指 ...

  5. JDK自带的监控分析工具JConsole

    非常多开发人员认为自己懂Java编程.事实是大多数开发人员都仅仅领会到了Java平台的皮毛.所学也仅仅够应付工作. 作者将深度挖掘Java平台的核心功能.揭示一些鲜为人知的事实.帮助您解决最棘手的编程 ...

  6. hosts目录位置

    C:\WINDOWS\system32\drivers\etc 版权声明:本文博客原创文章,博客,未经同意,不得转载.

  7. ashx一般处理程序和HttpHandler

    asp.net项目中,使用.ashx的文件(一般处理程序)可以用于处理客户端发送来的请求,并将服务器端的处理结果返回给客户端.它能返回的类型可以是文本.或者图片.有时候,我们可以在项目中使用.cs的文 ...

  8. ACdream 1427 Nice Sequence

    主题链接:http://115.28.76.232/problem? pid=1427 Nice Sequence Time Limit: 12000/6000MS (Java/Others)Memo ...

  9. Bye,IE!服务互联网20年IE终于要退役了

    美国当地时间16日中午,Microsoft Edge官微发表了祝词:Internet Explorer 20岁生日快乐!你在过去做出了巨大贡献,今后由我继续发扬光大.服务互联网20年之后,IE终于要退 ...

  10. C#值传递和按引用传递

    知识点: 值类型和引用类型  为值类型,,据        对于引用类型来说,栈中存储的是堆中对象的地址 值传递和引用传递 对于值传递,传递的是栈中保存的数据        对于引用传递.传递的是栈本 ...