小编Jos*_*hua的帖子

使用两个名称在C中调用相同函数的首选方法

我知道至少有三种流行的方法可以使用多个名称来调用相同的函数.我实际上没有听说有人为此目的使用第四种方法.

1).可以使用#defines:

int my_function (int);


#define my_func my_function
Run Code Online (Sandbox Code Playgroud)

要么

#define my_func(int (a)) my_function(int (a))
Run Code Online (Sandbox Code Playgroud)

2).嵌入式函数调用是另一种可能性

int my_func(int a) {
    return my_function(a);
}
Run Code Online (Sandbox Code Playgroud)

3).在链接器中使用弱别名:

int my_func(int a) __attribute__((weak, alias("my_function")));
Run Code Online (Sandbox Code Playgroud)

4).功能指针:

int (* const my_func)(int) = my_function;
Run Code Online (Sandbox Code Playgroud)

我需要多个名称的原因是数学库具有相同方法的多个实现.

例如,我需要一种有效的方法来计算标量浮点数的平方根.所以我可以使用math.h的sqrt().这不是很有效.所以我写了一两个其他方法,比如使用牛顿方法.问题是每种技术在某些处理器上更好(在我的情况下是微控制器).所以我希望编译过程选择最好的方法.

我认为这意味着最好使用宏或弱别名,因为这些技术可以很容易地在头文件中的几个#ifdef语句中进行分组.这简化了维护(相对).也可以使用函数指针,但它必须在源文件中,头文件中的常规函数​​的extern声明.

您认为哪种方法更好?


编辑:

从提议的解决方案中,似乎有两个重要问题我没有提到.

问:用户主要使用C/C++吗?

答:所有已知的开发都将采用C/C++或汇编语言.我正在设计这个库供我个人使用,主要用于裸机项目.将没有或最小的操作系统功能.在完整的操作系统中使用它的可能性很小,这需要考虑语言绑定.由于这是为了个人成长,因此在流行的嵌入式操作系统上学习库开发将是有利的.

问:用户是否需要/想要一个暴露的库?

:到目前为止,是的.由于它只是我,我想对测试后使用的每个处理器进行直接修改.这是测试套件有用的地方.所以一个暴露的图书馆会有所帮助.另外,特定功能的每个"最佳实现"可能具有失败的条件.此时,必须决定谁解决问题:用户或图书馆设计师.用户需要一个公开的库来解决失败的情况.我既是"用户"又是"图书馆设计师".两者都允许几乎更好.然后非实时应用程序可以让库解决所有稳定性问题,但是实时应用程序可以考虑算法速度/空间与算法稳定性.

c embedded function

17
推荐指数
3
解决办法
3614
查看次数

在内核套接字编程中模拟select()和poll()的效果

我正在开发的一个Linux内核驱动程序是在内核中使用网络通信(sock_create(),sock->ops->bind()等等).

问题是将有多个套接字从中接收数据.所以,我需要的东西,将模拟select()poll()在内核空间.由于这些函数使用文件描述符,我不能使用系统调用,除非我使用系统调用来创建套接字,但这似乎是不必要的,因为我在内核中工作.

所以我想sock->sk_data_ready在我自己的handler(custom_sk_data_ready())中包装默认处理程序,这将解锁一个信号量.然后我可以编写自己的kernel_select()函数来尝试锁定信号量并进行阻塞等待直到它打开.这样,内核函数就会进入休眠状态,直到信号量被解锁为止custom_sk_data_ready().一旦kernel_select()获得锁定,它就会解锁并调用custom_sk_data_ready()重新锁定它.所以唯一额外的初始化是custom_sk_data_ready()在绑定套接字之前运行,这样第一次调用custom_select()就不会错误地触发.

我看到一个可能的问题.如果发生多个接收,则多次调用custom_sk_data_ready()将尝试解锁信号量.因此,为了不丢失多个调用并跟踪sock正在使用的调用,必须有一个表或指向正在使用的套接字的指针列表.并且custom_sk_data_ready()必须在表/列表中标记它传递的套接字.

这种方法听起来好吗?或者,在使用标准系统调用时,我是否应该努力解决用户/内核空间问题?

初步调查结果:

sock结构中的所有回调函数都在中断上下文中调用.这意味着他们无法入睡.为了允许主内核线程在就绪套接字列表上休眠,使用互斥锁,但custom_sk_data_ready()必须像互斥锁上的自旋锁一样(mutex_trylock()重复调用).这也意味着任何动态分配都必须使用该GFP_ATOMIC标志.


附加可能性:

对于每个打开的套接字,用sk_data_ready()自定义的套接字替换每个套接字(custom_sk_data_ready())并创建一个worker(struct work_struct)和工作队列(struct workqueue_struct).process_msg()每个工人都将使用一个常用功能.创建一个内核模块级全局列表,其中每个列表元素都有一个指向套接字的指针并包含工作者结构.当数据在套接字上准备就绪时,custom_sk_data_ready()将执行并找到具有相同套接字的匹配列表元素,然后queue_work()使用list元素的工作队列和worker 进行调用.然后process_msg()调用该函数,并且可以通过struct work_struct *参数的内容(地址)找到匹配的列表元素,或者使用container_of()宏来获取包含工作者结构的列表结构的地址.

哪种技术最健全?

sockets linux networking kernel system-calls

12
推荐指数
1
解决办法
2652
查看次数

实现mmap()的内核驱动程序是否必须创建字符设备?

我正在尝试编写一个内核驱动程序来管理物理上连续和可DMA的内存的一些内存块(我正在使用,kmalloc()因为这些只是DMA流).要将某些功能提取到用户空间,这个内存将mmap()使用自己的实现来编辑mmap().我一直在使用Linux设备驱动程序以及在Google中显示的不良示例作为我的主要信息来源.

mmap()(my_mmap()现在称之为)需要在内核中注册.它似乎是使用a执行此操作的唯一有效方法struct file_operations,但这需要为其创建字符设备和物理位置.我不想那样做.我只想为用户空间应用程序创建一个虚拟地址来访问内存缓冲区,而不是创建任何文件来映射内存缓冲区.这可能吗?

我确实发现帧缓冲区也有一个与mmap()实现相同的结构,但这太过分了.这和它增加了更多的未知数.

据我所知,只要我对失去的灵活性感到满意,my_mmap()就可以完成繁重的工作remap_pfn_range().否则我将不得不实现一个本地nopages()并使用a注册它struct vm_operations_struct.它是否正确?

buffer mmap driver linux-kernel dma

4
推荐指数
1
解决办法
3488
查看次数

重用的命名结构作为嵌套结构会触发GCC中的重定义错误

这是一个人为的例子,但表达了核心问题.我有一个union和一个结构,它具有来自现有代码库的相同嵌套结构:

typedef union _MyUnion
{
  unsigned int A;
  struct _MyNestedStruct
  {
    int field
  } MyNestedStruct;
} MyUnion;
Run Code Online (Sandbox Code Playgroud)

typedef struct _MyStruct
{
  struct _MyNestedStruct
  {
    int field
  } MyNestedStruct;
} MyStruct;
Run Code Online (Sandbox Code Playgroud)

如果我在Green Hills Compiler(GHC)下编译,那么没有问题.在GCC下编译会给出错误"错误:重新定义'struct _MyStruct'".

首先,为什么我能够使用命名结构成功编译为嵌套结构?我怀疑GHC正在编译一些C++规则,或者它支持嵌套结构中的命名结构.

第二,什么才能让我成功编译而不需要任何重大的代码更改?我知道我可以从嵌套结构中删除_MyNestedStruct,但这会产生什么后果吗?

c struct unions

2
推荐指数
1
解决办法
1086
查看次数