- 浏览: 161311 次
- 性别:
- 来自: 大连->北京
文章分类
最新评论
-
netkongjian:
不错的界面控件知识,感谢分享!
界面测试 -
Tu_Bie:
赞一个。
servlet实现文件上传 -
心惶惶呀:
...
ORACLE和SQL语法区别归纳 -
ccfangle:
:idea:
我出现的原因是:标签重复了~
The content of element type "struts-config" must match 解决方案 -
zxl10059:
嗯,写的不错可以考虑自己写一个分页类page基本就可以明白是怎 ...
MySQL分页
/*
* fs/timerfd.c
*
* Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
*
*
* Thanks to Thomas Gleixner for code reviews and useful comments.
*
*/
#include <linux/file.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/time.h>
#include <linux/hrtimer.h>
#include <linux/anon_inodes.h>
#include <linux/timerfd.h>
#include <linux/syscalls.h>
struct timerfd_ctx {
struct hrtimer tmr;
ktime_t tintv;
wait_queue_head_t wqh;
u64 ticks;
int expired;
int clockid;
};
//该函数是timerfd的定时器超时函数。在timerfd超时时,该函数会设置定时器
//超时标记位;增加定时器超时次数(在设置定时器循环模式时,可能会出现多//次超时没有被处理的情况);唤醒一个等待队列,从而唤醒可能存在的正被阻//塞的read、select。
static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr)
{
struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx, tmr);
unsigned long flags;
//spin_lock_irqsave函数的作用是采用锁机制保证变量的正确性,但是在过程
//中可能会出现死锁的情况,所以采用一个中断状态来解决这样的问题,与
//下面的spin_lock_irqrestore相对应。
spin_lock_irqsave(&ctx->wqh.lock, flags);
ctx->expired = 1;// 设置定时器超时标记位
ctx->ticks++; //增加定时器超时次数
wake_up_locked(&ctx->wqh); //唤醒一个等待队列
spin_unlock_irqrestore(&ctx->wqh.lock, flags);
return HRTIMER_NORESTART;
}
static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
{
ktime_t remaining;
remaining = hrtimer_expires_remaining(&ctx->tmr);
return remaining.tv64 < 0 ? ktime_set(0, 0): remaining;
}
//一些初始化的工作
static void timerfd_setup(struct timerfd_ctx *ctx, int flags,
const struct itimerspec *ktmr)
{
enum hrtimer_mode htmode;
ktime_t texp;
htmode = (flags & TFD_TIMER_ABSTIME) ?
HRTIMER_MODE_ABS: HRTIMER_MODE_REL;
texp = timespec_to_ktime(ktmr->it_value);
ctx->expired = 0;
ctx->ticks = 0;
ctx->tintv = timespec_to_ktime(ktmr->it_interval);
hrtimer_init(&ctx->tmr, ctx->clockid, htmode);
hrtimer_set_expires(&ctx->tmr, texp);
ctx->tmr.function = timerfd_tmrproc;
if (texp.tv64 != 0)
//hrtimer_start函数将一个hrtimer加入到一个按照到期时间排序的红黑树中
hrtimer_start(&ctx->tmr, texp, htmode);
}
//timerfd_release函数释放timerfd_create函数中申请的资源,删除已分配的定时//器。
static int timerfd_release(struct inode *inode, struct file *file)
{
struct timerfd_ctx *ctx = file->private_data;
//hrtimer_cancel函数的作用是删除一个正在排队的定时器。这里分三种情况,一种是定
//时器已到期,并且设置了软中断模式;第二种是没有到期,还在红黑树中;第三种是
//定时器正在执行。
hrtimer_cancel(&ctx->tmr);
kfree(ctx); //释放内核空间
return 0;
}
/*timerfd_poll将timerfd的等待队列登记到一个poll_table,从而在定时器超时时能唤醒select系统调用。
*/
static unsigned int timerfd_poll(struct file *file, poll_table *wait)
{
struct timerfd_ctx *ctx = file->private_data;
unsigned int events = 0;
unsigned long flags;
poll_wait(file, &ctx->wqh, wait); //增加一个等待队列到poll_table
spin_lock_irqsave(&ctx->wqh.lock, flags);
if (ctx->ticks)
events |= POLLIN;
spin_unlock_irqrestore(&ctx->wqh.lock, flags);
return events;
}
/*
*timerfd_read函数是文件操作read的内核实现,读到的是定时器的超时次数。
*该函数在阻塞模式下会把自身挂到timerfd的等待队列中,等待定时器超时时
*被唤醒。
*/
static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
struct timerfd_ctx *ctx = file->private_data;
ssize_t res;
u64 ticks = 0;
DECLARE_WAITQUEUE(wait, current);
if (count < sizeof(ticks))
return -EINVAL;
spin_lock_irq(&ctx->wqh.lock);
res = -EAGAIN;
if (!ctx->ticks && !(file->f_flags & O_NONBLOCK)) {
__add_wait_queue(&ctx->wqh, &wait);
for (res = 0;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (ctx->ticks) {
res = 0;
break;
}
if (signal_pending(current)) {
res = -ERESTARTSYS;
break;
}
spin_unlock_irq(&ctx->wqh.lock);
schedule();
spin_lock_irq(&ctx->wqh.lock);
}
__remove_wait_queue(&ctx->wqh, &wait);
__set_current_state(TASK_RUNNING);
}
if (ctx->ticks) {
ticks = ctx->ticks;
if (ctx->expired && ctx->tintv.tv64) {
/*
* If tintv.tv64 != 0, this is a periodic timer that
* needs to be re-armed. We avoid doing it in the timer
* callback to avoid DoS attacks specifying a very
* short timer period.
*/
ticks += hrtimer_forward_now(&ctx->tmr,
ctx->tintv) - 1;
hrtimer_restart(&ctx->tmr);
}
ctx->expired = 0;
ctx->ticks = 0;
}
spin_unlock_irq(&ctx->wqh.lock);
if (ticks)
res = put_user(ticks, (u64 __user *) buf) ? -EFAULT: sizeof(ticks);
return res;
}
static const struct file_operations timerfd_fops = {
.release = timerfd_release,
.poll = timerfd_poll,
.read = timerfd_read,
};
//根据文件描述符获得一个file的结构体
static struct file *timerfd_fget(int fd)
{
struct file *file;
file = fget(fd);
if (!file)
return ERR_PTR(-EBADF);
if (file->f_op != &timerfd_fops) {
fput(file);
return ERR_PTR(-EINVAL);
}
return file;
}
/*
*做一些定时器的初始化工作;
*调用hrtimer_init初始化一个hrtimer;
*调用anon_inode_getfd分配一个dentry,并得到一个文件号fd,同时传入timerfd
*的文件操作指针struct file_operations timerfd_fops,anno_inode_getfd是文件系统
*anon_inodefs的一个帮助函数。anon文件系统比较简单,整个文件系统只有一
*个inode节点,其实现代码可以在fs/anon_inodes.c中找到。
*/
SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
{
int ufd;
struct timerfd_ctx *ctx;
/* Check the TFD_* constants for consistency. */
BUILD_BUG_ON(TFD_CLOEXEC != O_CLOEXEC);
BUILD_BUG_ON(TFD_NONBLOCK != O_NONBLOCK);
if ((flags & ~TFD_CREATE_FLAGS) ||
(clockid != CLOCK_MONOTONIC &&
clockid != CLOCK_REALTIME))
return -EINVAL;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
init_waitqueue_head(&ctx->wqh);
ctx->clockid = clockid;
hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
flags & TFD_SHARED_FCNTL_FLAGS);
if (ufd < 0)
kfree(ctx);
return ufd;
}
//timerfd_settime最终会调用hrtimer_start启动定时器,其超时函数被设置为timerfd_tmrproc。
/*此函数用于设置新的超时时间,并开始计时。
*参数ufd是timerfd_create返回的文件句柄。
*参数flags为1代表设置的是绝对时间;为0代表相对时间。
*参数utmr为需要设置的时间。
*参数otmr为定时器这次设置之前的超时时间。
*函数返回0代表设置成功。
*/
SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
const struct itimerspec __user *, utmr,
struct itimerspec __user *, otmr)
{
struct file *file;
struct timerfd_ctx *ctx;
struct itimerspec ktmr, kotmr;
if (copy_from_user(&ktmr, utmr, sizeof(ktmr)))
return -EFAULT;
if ((flags & ~TFD_SETTIME_FLAGS) ||
!timespec_valid(&ktmr.it_value) ||
!timespec_valid(&ktmr.it_interval))
return -EINVAL;
file = timerfd_fget(ufd);
if (IS_ERR(file))
return PTR_ERR(file);
ctx = file->private_data;
/*
* We need to stop the existing timer before reprogramming
* it to the new values.
*/
for (;;) {
spin_lock_irq(&ctx->wqh.lock);
if (hrtimer_try_to_cancel(&ctx->tmr) >= 0)
break;
spin_unlock_irq(&ctx->wqh.lock);
cpu_relax();
}
/*
* If the timer is expired and it's periodic, we need to advance it
* because the caller may want to know the previous expiration time.
* We do not update "ticks" and "expired" since the timer will be
* re-programmed again in the following timerfd_setup() call.
*/
if (ctx->expired && ctx->tintv.tv64)
hrtimer_forward_now(&ctx->tmr, ctx->tintv);
kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
kotmr.it_interval = ktime_to_timespec(ctx->tintv);
/*
* Re-program the timer to the new value ...
*/
timerfd_setup(ctx, flags, &ktmr);
spin_unlock_irq(&ctx->wqh.lock);
fput(file);
if (otmr && copy_to_user(otmr, &kotmr, sizeof(kotmr)))
return -EFAULT;
return 0;
}
//此函数用于获得定时器距离下次超时还剩下的时间。
//如果调用时定时器已经到期,并且该定时器处于循环模式,那么调用此函数之后定时器重新开始计时。
SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr)
{
struct file *file;
struct timerfd_ctx *ctx;
struct itimerspec kotmr;
file = timerfd_fget(ufd);
if (IS_ERR(file))
return PTR_ERR(file);
ctx = file->private_data;
spin_lock_irq(&ctx->wqh.lock);
if (ctx->expired && ctx->tintv.tv64) {
ctx->expired = 0;
ctx->ticks +=
hrtimer_forward_now(&ctx->tmr, ctx->tintv) - 1;
hrtimer_restart(&ctx->tmr);
}
kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
kotmr.it_interval = ktime_to_timespec(ctx->tintv);
spin_unlock_irq(&ctx->wqh.lock);
fput(file);
return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0;
}
发表评论
-
为嘛BIOS将MBR读入0x7C00地址处(x86平台下)
2012-11-27 14:06 1771对于很多人来讲0x7C00这个地址是很神秘的,不知道这是 ... -
挖个坑,通过一个bug学习scsi~
2012-10-23 15:55 1364开始来点前期准备的知识,主要关于Linux的I/O 路线 ... -
Solaris下如何查看boot_archive以及制作定制版boot_archive
2012-10-23 15:53 917从标题可以得知,分为两步,首先是查看,继而是修改定制。 ... -
vim系列教程(1)基础操作
2011-11-27 20:49 1085总结下本人平时所使用的各种工具以及语言的快速入门教程以及 ... -
code2pdf
2011-06-29 12:10 1023http://www.code2pdf.com http:/ ... -
Perl在vim下的一些基本SYNTAX设置
2010-10-09 13:58 1875perl 的语法高亮有一些 ... -
ubuntu 10.04 电子科技大学源 校园网推荐
2010-06-12 10:59 2263电子科技大学源(校园网推荐,快) deb http:// ... -
Linux环境变量设置--总结
2009-10-20 09:27 31001、引言 在 linux系统 ... -
Linux下的脚本语言--Perl和Python Intro
2009-10-15 10:26 3247到Linux下的脚本语言, ... -
CentOS 5.3配置软件源以及CVS服务器
2009-09-24 20:05 15921 、安装完 CentOS 5.3 之后,首先要保证可以 ... -
Unix 哲学
2009-09-24 09:51 890Unix 哲学: 一:小即是美。 二:让程序只做好一件事 ... -
发一张我的桌面
2009-08-24 11:07 858我的Linux下的桌面,纯属娱乐.... -
Debian/Ubuntu的NFS配置
2009-08-21 17:07 1600Debian/Ubuntu的NFS配置 简介 :NFS(Net ... -
ubuntu 镜像的制作
2009-07-20 16:08 3764Ubuntu Customization Kit 简称 UCK ... -
Linux 由浅入深
2009-07-16 22:44 9561.掌握至少50个以上的常用命令。(GOT) 2.熟悉Gno ... -
Debian 安装Flash插件
2009-07-12 09:15 3759下载install_flash_player_10_linux ... -
Debian 源的设置
2009-07-11 20:57 1651Debian 源的设置 作者:Hily 原始链接:http: ... -
嵌入式Linux游戏开发一
2009-06-22 14:13 14901、引言 Linux由于其具有内核强大且稳定,易于扩展 ... -
ubuntu 9.04更新源
2009-05-06 09:33 127191.sudo gedit /etc/apt/sources.l ... -
Linux 下mysql的卸载
2009-04-15 14:41 2410前段时间安装了Mysql,但是有些问题,就想把他卸载了, ...
相关推荐
NULL 博文链接:https://bnmnba.iteye.com/blog/2322332
压缩包中的文件"FS_C"可能是包含了上述`Complex`类实现的源代码文件。如果要深入了解这个程序的工作原理,你可以解压文件并查看源代码,了解具体的实现细节。 总之,这个项目涉及的知识点包括: 1. 复数的概念及其...
本文将深入探讨Node.js异步IO的实现,并结合给定的资源进行分析。 首先,异步I/O是Node.js的核心特性之一,它允许程序在等待I/O操作完成时继续执行其他任务,从而提高了整体的执行效率和系统资源利用率。在传统的...
小雉系统升级包-4.181.1507,系统tcp使用bbr,提升tcp效率;系统增加邮件系统,可收发邮件;详细信息请访问: <a href="http://...
使用命令即可实现./patch-ker.sh c /home/linux-2.6.32.2 上面这个命令完成了三件事情(也可以手动修改实现) (1)修改内核fs/Kconfig,增加了两行 # Patched by YAFFS source "fs/yaffs2/Kconfig" (2)修改内核fs/...
有框主程序,可以移动http://page18.ctfile.com/fs/gNL152134545 无框主程序,不能移动http://page18.ctfile.com/fs/WKz152134542 2、再下载分省图资(下载后将2个文件拷入NaviOne目录下就可以了) ...
在C语言编程中,通常通过在`libc`(标准C库)中定义的函数来访问这些系统调用。`libc`为许多系统调用提供了封装,使得开发者可以更方便地调用它们。关于系统调用的更多信息可以在手册页(man pages)的第二节找到,...
在给定的压缩包"esp_littlefs:用于ESP-IDF的LittleFS端口.zip"中,包含了一个名为"esp_littlefs-master"的项目,这是ESP-IDF对LittleFS文件系统的移植。 LittleFS是一种轻量级的文件系统,设计用于嵌入式设备,...
| 8 | creat | 创建文件或设备(更多信息参见`man2 open`) | `fs/open.c` | | 9 | link | 为文件创建新的名称 | `fs/namei.c` | | 10 | unlink | 删除文件名及其可能指向的文件 | `fs/namei.c` | | 11 | execve | ...
- 源码位置:`fs/open.c` 6. **close** - 描述:关闭文件描述符。 - 源码位置:`fs/open.c` 7. **waitpid** - 描述:等待子进程结束。 - 源码位置:`kernel/exit.c` 8. **creat** - 描述:创建文件或设备(更...
GPIO模拟I2C的程序实现 #include <linux/module.h> #include <linux/config.h> #include <linux/errno.h> #include <linux/miscdevice.h> #include <linux/fcntl.h> #include <linux/init.h> #include <linux/delay...
这是一个简单的基于C语言的防火墙,#include <linux/kernel.h> #include <linux/ip.h> #include <linux/module.h> #include <linux/netdevice.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #...
linux tcp/ip分析 两台主机建立udp通信所走过的函数列表: | sys_read fs/read_write.c | sock_read net/socket.c | sock_recvmsg net/socket.c | inet_recvmsg net/ipv4/af_inet.c | udp_recvmsg net/ipv4/udp.c | ...
本文件旨在深入分析Linux操作系统的源代码,通过对核心部分的解读来帮助读者更好地理解Linux内核的工作原理。 #### 二、Linux操作系统特性 1. **抢先式多任务处理**:Linux支持真正的多任务处理,能够同时运行多个...
### Linux 2.6.26.6 内核下的 LED 驱动程序分析 在深入探讨这个特定的 LED 驱动程序之前,我们首先来了解一下 Linux 内核和驱动开发的基本概念。 #### Linux 内核简介 Linux 是一个开源的操作系统内核,由 Linus ...
├─fs │ bitmap.c │ block_dev.c │ buffer.c │ char_dev.c │ exec.c │ fcntl.c │ file_dev.c │ file_table.c │ inode.c │ ioctl.c │ Makefile │ namei.c │ open.c │ pipe.c │ read_write.c │ stat....
#include <linux/fs.h> #include <linux/proc_fs.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/init.h> #include <linux/poll.h> #include <asm/uaccess.h> #...