• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
导航菜单
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • windows
  • 服务器硬件
  • 服务器运维
  • 云计算
  • 虚拟化
  • IIS教程
  • Linux
  • Apache
  • Ftp
  • DNS
  • Nginx
您的位置:首页 > 服务器 >windows > 一个IO的传奇一生 (6) --

一个IO的传奇一生 (6) --

作者:网友 字体:[增加 减小] 来源:互联网

本文主要包含一个io口控制两个灯,agar.io游戏,io,温氏io登录,agar.io游戏中文版等服务器相关知识,网友希望可以进行参考

IO调度器

 

当IO旅行到调度器的时候,发现自己受到的待遇竟然很不一样,有些IO倚仗着特权很快就放行了;有些IO迟迟得不到处理,甚至在有些系统中居然饿死!面对这样的现状,IO显然是很不高兴的,凭什么别人就能被很快送到下一个旅程,自己需要在调度器上耗费青春年华?这里是拼爹的时代,人家出身好,人家是读请求,人家就可以很快得到资源。咱们是写请求,出生贫寒,只能等着,但也不会让你饿死。这就是我们常见的deadline策略。在更加糟糕的地方,deadline都没有,拼的是家族血脉关系,相邻的IO可以很快处理掉,其他的等着吧,那就会出现饿死的情况。这就是我们常说的noop策略,其实就是Linus电梯。在文明一点的社会,大家会比较公平,从应用的整体来看,大家会享有相同的IO带宽,但是,从IO的个体来看,公平性还是没有的。这个社会没有绝对的公平,只要保证所有家庭的公平性,那么社会就会比较和谐。当然,我们发现有些家庭应用)不是特别合群,我们也可以对其进行惩罚,IO带宽的分配就会对其进行缩减。这就是我们常见的CFQ策略。在IO调度器层,可以有很多的策略,不同的系统可以定义不同的策略,目的都是在与更好的聚合IO,并且对不同的应用进行QOS控制。

在Linux系统中,可以注册自己的调度算法,如果不注册自己的调度器,那么可以采用上述提到的三种调度器之一。其中,deadline是在Linus电梯的基础上发展起来的,其对读写请求进行了有区别的调度,还会考虑到IO饥饿的情况。最为传统的调度器不能规避IO饥饿问题。CFQ调度器考虑了应用的公平性,在很多情况下可以得到最佳性能,有关于这三种调度器的设计比较会在下面篇章中详细阐述。

当IO请求通过generic_make_request进行转发时,如果被访问的设备是一个有queue的块设备,那么系统会调用blk_queue_bio函数进行bio的调度合并。blk_queue_bio函数说明如下:

void blk_queue_bio(struct request_queue *q, struct bio *bio)
{
const bool sync = !!(bio->bi_rw & REQ_SYNC);
struct blk_plug *plug;
int el_ret, rw_flags, where = ELEVATOR_INSERT_SORT;
struct request *req;
unsigned int request_count = 0;
/*
* low level driver can indicate that it wants pages above a
* certain limit bounced to low memory (ie for highmem, or even
* ISA dma in theory)
*/
blk_queue_bounce(q, &bio);
if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
spin_lock_irq(q->queue_lock);
where = ELEVATOR_INSERT_FLUSH;
goto get_rq;
}
/*
* Check if we can merge with the plugged list before grabbing
* any locks.
*/
/* 尝试将bio合并到当前plugged的请求队列中 */
if (attempt_plug_merge(q, bio, &request_count))
return;
spin_lock_irq(q->queue_lock);
/* elv_merge是核心函数,找到bio前向或者后向合并的请求 */
el_ret = elv_merge(q, &req, bio);
if (el_ret == ELEVATOR_BACK_MERGE) {
/* 进行后向合并操作 */
if (bio_attempt_back_merge(q, req, bio)) {
if (!attempt_back_merge(q, req))
elv_merged_request(q, req, el_ret);
goto out_unlock;
}
} else if (el_ret == ELEVATOR_FRONT_MERGE) {
/* 进行前向合并操作 */
if (bio_attempt_front_merge(q, req, bio)) {
if (!attempt_front_merge(q, req))
elv_merged_request(q, req, el_ret);
goto out_unlock;
}
}
/* 无法找到对应的请求实现合并 */
get_rq:
/*
* This sync check and mask will be re-done in init_request_from_bio(),
* but we need to set it earlier to expose the sync flag to the
* rq allocator and io schedulers.
*/
rw_flags = bio_data_dir(bio);
if (sync)
rw_flags |= REQ_SYNC;
/*
* Grab a free request. This is might sleep but can not fail.
* Returns with the queue unlocked.
*/
/* 获取一个empty request请求 */
req = get_request_wait(q, rw_flags, bio);
if (unlikely(!req)) {
bio_endio(bio, -ENODEV);    /* @q is dead */
goto out_unlock;
}
/*
* After dropping the lock and possibly sleeping here, our request
* may now be mergeable after it had proven unmergeable (above).
* We don't worry about that case for efficiency. It won't happen
* often, and the elevators are able to handle it.
*/
/* 采用bio对request请求进行初始化 */
init_request_from_bio(req, bio);
if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags))
req->cpu = raw_smp_processor_id();
plug = current->plug;
if (plug) {
/*
* If this is the first request added after a plug, fire
* of a plug trace. If others have been added before, check
* if we have multiple devices in this plug. If so, make a
* note to sort the list before dispatch.
*/
if (list_empty(&plug->list))
trace_block_plug(q);
else {
if (!plug->should_sort) {
struct request *__rq;
__rq = list_entry_rq(plug->list.prev);
if (__rq->q != q)
plug->should_sort = 1;
}
if (request_count >= BLK_MAX_REQUEST_COUNT) {
/* 请求数量达到队列上限值,进行unplug操作 */
blk_flush_plug_list(plug, false);
trace_block_plug(q);
}
}
/* 将请求加入到队列 */
list_add_tail(&req->queuelist, &plug->list);
drive_stat_acct(req, 1);
} else {
/* 在新的内核中,如果用户没有调用start_unplug,那么,在IO scheduler中是没有合并的,一旦加入到request queue中,马上执行unplug操作,这个地方个人觉得有点不妥,不如以前的定时调度机制。对于ext3文件系统,在刷写page cache的时候,都需要首先执行start_unplug操作,因此都会进行request/bio的合并操作。 */
spin_lock_irq(q->queue_lock);
/* 将request加入到调度器中 */
add_acct_request(q, req, where);
/* 调用底层函数执行unplug操作 */
__blk_run_queue(q);
out_unlock:
spin_unlock_irq(q->queue_lock);
}
}

对于blk_queue_bio函数主要做了三件事情:

1)进行请求的后向合并操

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 一个IO的传奇一生 (6) --
  • 一个IO的传奇一生 (4) ---

相关文章

  • Hadoop (CDH4发行版)集群部署 (部署脚本,namenode高可用,hadoop管理)
  • Raid阵列与lvm逻辑卷组(下)
  • Windows操作系统下 如何安装Memcache软件
  • Winodws Server 2008 安装手记
  • Windows 2003中Rewrite组件为IIS设置伪静态
  • Mac OS X/windows下启用Mod Rewrite和.htaccess
  • 选取存储设备构建数据容灾备份系统方法
  • Windows 系统常用MMC控制台快捷命令
  • w3wp.exe进程占用内存过高解决办法
  • windows rsync两台服务器目录同步功能实现

文章分类

  • windows
  • 服务器硬件
  • 服务器运维
  • 云计算
  • 虚拟化
  • IIS教程
  • Linux
  • Apache
  • Ftp
  • DNS
  • Nginx

最近更新的内容

    • 基于lvs的 heartbeat实现的HA群集
    • 巧用net user命令 限定系统用户登录时间
    • Windows系统中IIS防盗链设置详细介绍
    • discuz 常见报错
    • Windows创建.htaccess文件方法总结
    • windows服务器iis“Http 500内部服务器错误”解决办法
    • DirectAdmin 日志路径各种系统中查看方法
    • Windows Server 2008网络性能
    • 如何更改SQL Server 2008 R2的排序规则!
    • 免疫Windows系统 不受恶意代码骚扰

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有