再次回到disksim_simulate_event()函数
主体:
1 | void disksim_simulate_event (int num) |
对event的type类型的宏定义在disksim_global.h
中有:
1 | /* Event Type Ranges */ |
函数getnextevent()
在disksim.c中的源码:
1 | INLINE static event * getnextevent () |
getnextevent
函数最主要的是通过调用getfromintq
从调度队列中取出一个event,取出这个event的时候当前的系统时间simtime等于这个event所指定的time。但是对于函数中当取到的event的类型为NULL_EVENT的处理:
1 | if (curr->type == NULL_EVENT) { |
我目前猜测,当event类型为NULL_EVENT是表示当前的bus channel是空闲的,可以服务读写请求,是依据这句话猜测的
1 | if ((disksim->iotrace) && io_using_external_event(curr)) |
这里又涉及了disksim结构体的一个变量iotrace
这个变量最早出现和配置是在disksim_setup_disksim()
函数中,关于这个函数的详细解释在明天的笔记中讲初始化的时候会研究,先看其关于iotrace
配置的代码段:
1 | if(strcmp(argv[5], "0") != 0) { |
这里需要解释下关于仿真器disksim的使用在Linux终端输入的命令参数是:disksim \参数文件 \输出文件 \ trace输入格式\trace文件\synthgen(是否激活disksim内部负载生成仿真,一般为0)
对应在main(argv)的参数表:argv[0],…,argv[5]。
当disksim->synthgen=1
表示disksim自己生成trace进行仿真,disksim->iotrace
为非零表示使用外部trace,为0表示不用外部负载。
那么看下io_using_external_event(event *curr)
函数是干什么的,该函数在disksim_iosim.c中定义:
1 | int io_using_external_event (event *curr) |
这个函数判断输入的event 指针指向的内容和当前的io_extq指针指向的内容是否相同,相同返回1且将curr的type置为io_extq_type
(这是一个宏),不同返回0。io_extq
,io_extq_type
都是宏,在disksim_iosim.c文件头部(删除现在不必要的显示)就声明了:
1 | /* one remapping #define for each variable in iosim_info_t */ |
又扯到disksim结构体的定义了,iosim_info
是disksim中对硬件相关模型的定义一种,且看节选代码:
1 |
|
上述的结构体在disksim_global.h中只是声明,具体的定义都在各自的文件里面,如iosim_info
在disksim_iosim.c中才定义:
1 | typedef struct iosim_info { |
现在可以理解io_extq
就是一个event类型的指针,io_extq_type
就是个int型的数和event中的type是一样的,那么io_extq_type
有那些宏定义可以选择,我猜测和前面的event的type类型选择是一样的。把前面的if的语句展开仔细看理解
1 | if ((disksim->iotrace) && io_using_external_event(curr)) { |
###总结getnextevent()函数
:
这么理解函数,从intq队列中取出一个event,如果该event的类型为NULL_EVENT时,getnextevent()
函数根据仿真采用负载为外部负载且调用io_using_external_event()
判断当前的event和io_extq指向的内容是否相同,若相同则把event的类型改成当前的io_extq_type
的类型,io_get_next_external_event()
函数应该能判断外部的负载输入是否结束,从而将disksim->stop_sim置为TRUE,结束仿真,如果外部负载不为空,即(temp = io_get_next_external_event(disksim->iotracefile)
返回不为空,则把该temp的类型置为NULL_EVENT,调用addtointq(temp);
将temp加入intq队列中,这么操作有点栈的意思。先从intq取栈顶的元素event,event的类型为NULL_EVENT则一般是为使用外部负载,需要判断外部负载判断结束时间驱动,没有结束,则将新的NULL_EVENT
的event类型(temp)压入栈(intq)。这是我目前的理解。
###该函数的继续延伸阅读getnextevent()函数
调用了io_get_next_external_event()
函数,在介绍这个函数之前,先引入了解处理I/O请求的结构体ioreq_event,在disksim_global.h
中有定义:
1 | typedef struct ioreq_ev { |
其实ioreq_event
和event
结构体可以强制类型转化的,这个在io_get_next_external_event()
函数里面有句话:
1 | ioreq_event *temp; |
getfromextrq
函数返回的是event结构体指针,这里突然理解了,event的结构体里面的
1 | char space[DISKSIM_EVENT_SPACESIZE]; |
其实就是为了将这部分内存字段转化为其他类型的时候存其他数据使用的。代码读到这突然觉得需要系统的捋一边系统的初始化过程和主要的结构体变量了,思路有点乱。