- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
首先,我了解如何使用函数指针和字符串或其他查找来实现调度表,这不是挑战。
我正在寻找的是某种在编译时向该表动态添加条目的方法。
我希望的代码结构类型是这样的:
Strategy.h - 包含调度程序和调度表定义的函数定义Strategy.c - 包含调度程序的代码
MyFirstStrategy.c - 包括 Strategy.h 并提供该策略的一个实现MyOtherStrategy.c - 包含 Strategy.h 并提供策略的第二个实现
这个想法是,将函数指针和策略名称插入调度表的代码不应该存在于 Strategy.c 中,而应该存在于单独的策略实现文件中,并且查找表应该在编译时以某种方式动态构建。
对于固定大小的调度表,这可以按如下方式进行管理,但我想要一个动态大小的表,我不希望 Strategy.c 实现必须包含实现的所有头文件,我会就像要在编译时而不是运行时构建的调度表。
固定大小示例
typedef void strategy_fn_t(int);
typedef struct {
char *strategyName;
strategy_fn_t *implementation;
} dispatchTableEntry_t;
#include "Strategy.h"
void firstStrategy( int param );
#include "Strategy.h"
void otherStrategy( int param );
#include "Strategy.h"
#include "MyFirstStrategy.h"
#include "MyOtherStrategy.h"
dispatchTableEntry_t dispatchTable[] = {
{ "First Strategy", firstStrategy },
{ "Other Strategy", otherStrategy }
};
int numStrategies = sizeof( dispatchTable ) / sizeof(dispatchTable[0] );
我真正想要的是一些预处理器魔术,我可以将其插入到策略实现文件中以自动处理,例如
#include "Strategy.h"
void firstStrategy( int param );
ADD_TO_DISPATCH_TABLE( "First Strategy", firstStrategy );
有什么想法吗?
最佳答案
在具有 gnu 链接器和编译器或兼容的东西的系统上,可以将某些对象放在不同的部分中。然后链接器将为该部分的开始和结束生成符号。使用它,您可以将所有结构放入不同对象的该部分,链接器将在链接时合并这些部分,您可以将它们作为数组访问。如果您在共享库中执行此操作,则需要进行更多操作,并且绝对不能在 ELF Linux/*BSD 之外移植。
我在 MacOS 和 a.out BSD 上做过类似的事情(虽然这个例子不会工作),但我丢失了那个代码。以下是如何在 Linux 上运行的示例:
$ cat link_set.c
#include <stdio.h>
struct dispatch_table {
const char *name;
void (*fun)(int);
};
#define ADD_TO_DISPATCH_TABLE(name, fun) \
static const struct dispatch_table entry_##fun \
__attribute__((__section__("link_set_dispatch_table"))) = \
{ name, fun }
int
main(int argc, char **argv)
{
extern struct dispatch_table __start_link_set_dispatch_table;
extern struct dispatch_table __stop_link_set_dispatch_table;
struct dispatch_table *dt;
for (dt = &__start_link_set_dispatch_table; dt != &__stop_link_set_dispatch_table; dt++) {
printf("name: %s\n", dt->name);
(*dt->fun)(0);
}
return 0;
}
void
fun1(int x)
{
printf("fun1 called\n");
}
ADD_TO_DISPATCH_TABLE("fun 1", fun1);
void
fun2(int x)
{
printf("fun2 called\n");
}
ADD_TO_DISPATCH_TABLE("fun 2", fun2);
$ cc -o link_set link_set.c
$ ./link_set
name: fun 1
fun1 called
name: fun 2
fun2 called
$
解释宏的作用。它创建了一个 struct dispatch_table ,我们希望它的名字是唯一的,因为你可能想在一个对象中多次使用它(如果你多次使用同一个函数,想出一些其他的方式来命名结构)并用gnu 扩展来指定对象应该结束的部分。如果我们将对象放入“some_section_name”,那么链接器将自动添加符号 __start_some_section_name 和 __end_some_section_name。然后我们可以在这些符号之间移动并获取我们放入该部分的所有结构。
更新了 MacOS 的工作示例:
#include <stdio.h>
#include <mach-o/ldsyms.h>
#include <mach-o/getsect.h>
#include <mach-o/loader.h>
struct dispatch_table {
const char *name;
void (*fun)(int);
};
#define ADD_TO_DISPATCH_TABLE(name, fun) \
static const struct dispatch_table entry_##fun \
__attribute__((__section__("__DATA,set_dt"))) = \
{ name, fun }
int
main(int argc, char **argv)
{
struct dispatch_table *start;
unsigned long sz;
intptr_t s;
int i;
s = (intptr_t)getsectdata("__DATA", "set_dt", &sz);
if (s == 0)
return 1;
s += _dyld_get_image_vmaddr_slide(0);
start = (struct dispatch_table *)s;
sz /= sizeof(*start);
for (i = 0; i < sz; i++) {
struct dispatch_table *dt = &start[i];
printf("name: %s\n", dt->name);
(*dt->fun)(0);
}
return 0;
}
void
fun1(int x)
{
printf("fun1 called\n");
}
ADD_TO_DISPATCH_TABLE("fun 1", fun1);
void
fun2(int x)
{
printf("fun2 called\n");
}
ADD_TO_DISPATCH_TABLE("fun 2", fun2);
这里的部分必须被称为“set_dt”,因为在这种可执行格式中部分名称的长度是有限的。
当然,如果你已经达到需要这个的程度,你肯定明白这一切都非常危险,不可移植,不能保证永远工作(我三年前的代码在当前版本上不起作用macos),没有类型或其他安全性,如果其他东西决定将东西放入具有相同名称的部分,那么东西最终会变成非常漂亮的烟花。但这是一个非常巧妙的技巧。我在两个大型项目中使用了这种方法,它确实节省了很多工作中央调度表不必在共享存储库中编辑,这曾经给每个人带来冲突。
关于c - 如何在 C 中实现动态调度表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11840651/
我有一个带有一些功能的perl对象。每个功能从主程序中调用一次。我想并行运行某些功能以节省时间。由于某些功能取决于先前功能的结果,因此我无法将它们全部一起运行。 我想到了这样的事情: 对于每个函数,保
首先,我的代码在这里: import schedule # see https://github.com/dbader/schedule import crawler def job(): p
从 11 月 1 日开始,我必须使用quartz调度程序每4个月安排一次任务。我使用 cronExpression 来实现同样的目的。但 cronExpression 每年都会重置。所以我的任务将在
我有以下代码块,它调用两个请求,但略有延迟。 final ActorRef actor1 = getContext().actorOf( ActorClass.prop
考虑到 Linux 的情况,我们为每个用户堆栈都有一个内核堆栈,据我所知,每当发生上下文切换时,我们都会切换到当前进程的内核模式。 这里我们保存当前进程的当前状态,寄存器,程序数据等,然后调度器(不确
我有将东西移植到 OpenBSD 的奇怪爱好。我知道它有 pthreads 问题,但在 2013 年 5 月发布版本之前我不会升级。我使用的是 5.0,我对 pthreads 还很陌生。我已经学习了
给定一组任务: T1(20,100) T2(30,250) T3(100,400) (execution time, deadline=peroid) 现在我想将截止日期限制为 Di = f * Pi
使用 Django 开发一个小型日程安排 Web 应用程序,在该应用程序中,人们被分配特定的时间与他们的上级会面。员工存储为模型,与表示时间范围和他们有空的星期几的模型具有 OneToMany 关系。
我想了解贪婪算法调度问题的工作原理。 所以我一直在阅读和谷歌搜索一段时间,因为我无法理解贪心算法调度问题。 我们有 n 个作业要安排在单个资源上。作业 (i) 有一个请求的开始时间 s(i) 和结束时
这是流行的 El Goog 问题的变体。 考虑以下调度问题:有 n 个作业,i = 1..n。有 1 台 super 计算机和无限的 PC。每个作业都需要先经过 super 计算机的预处理,然后再在P
假设我有一个需要运行多次的蜘蛛 class My_spider(Scrapy.spider): #spider def 我想做这样的事 while True: runner = Cra
我已将 podAntiAffinity 添加到我的 DeploymentConfig 模板中。 但是,pod 被安排在我预计会被规则排除的节点上。 我如何查看 kubernetes 调度程序的日志以了
我已经使用 React - Redux - Typescript 堆栈有一段时间了,到目前为止我很喜欢它。但是,由于我对 Redux 很陌生,所以我一直在想这个特定的话题。 调度 Redux 操作(和
我想按照预定的计划(例如,周一至周五,美国东部时间晚上 9 点至 5 点)运行单个 Azure 实例以减少账单,并且想知道最好的方法是什么。 问题的两个部分: 能否使用服务管理 API [1] 按预定
假设最小模块安装(为了简单起见),Drupal 的 index.php 中两个顶级功能的核心“职责”是什么? ? drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); me
我正在尝试使用 Racket(以前称为 PLT Scheme)连接 URL 调度。我查看了教程和服务器文档。我不知道如何将请求路由到相同的 servlet。 具体例子: #lang 方案 (需要网络服
我想在 Airflow (v1.9.0) 上运行计划。 我的DAG需要在每个月底运行,但我不知道如何编写设置。 my_dag = DAG(dag_id=DAG_ID, cat
我正在尝试在“httpTrigger”类型函数的 function.json 中设置计划字段,但计时器功能似乎未运行。我的目标是拥有一个甚至可以在需要时进行调度和手动启动的功能,而不必仅为了调度而添加
我正在尝试制定每周、每月的 Airflow 计划,但不起作用。有人可以报告可能发生的情况吗?如果我每周、每月进行安排,它就会保持静止,就好像它被关闭一样。没有错误信息,只是不执行。我发送了一个代码示例
我希望每两周自动更新一次我的表格。我希望我的函数能够被 firebase 调用。 这可能吗? 我正在使用 Angular 2 Typescript 和 Firebase。 最佳答案 仅通过fireba
我是一名优秀的程序员,十分优秀!