小编Vil*_*ray的帖子

从Linux内核模块中调用用户空间函数

我正在编写一个简单的Linux字符设备驱动程序,通过I/O端口将数据输出到一个硬件.我有一个函数执行浮点运算来计算硬件的正确输出; 不幸的是,这意味着我需要在用户空间中保留此功能,因为Linux内核不能很好地处理浮点运算.

这是设置的伪表示(请注意,此代码不执行任何特定操作,它只显示我的代码的相对布局):

用户空间功能:

char calculate_output(char x){
    double y = 2.5*x;
    double z = sqrt(y);

    char output = 0xA3;

    if(z > 35.67){
        output = 0xC0;
    }

    return output;
}
Run Code Online (Sandbox Code Playgroud)

内核空间代码:

unsigned i;
for(i = 0; i < 300; i++){
    if(inb(INPUT_PORT) & NEED_DATA){
        char seed = inb(SEED_PORT);
        char output = calculate_output(seed);
        outb(output, OUTPUT_PORT);
    }

    /* do some random stuff here */
}
Run Code Online (Sandbox Code Playgroud)

我想过ioctl用来传递来自用户空间函数的数据,但我不知道如何处理函数调用处于循环中并且在下一次调用calculate_output发生之前执行更多代码的事实.

我设想这个工作的方式是:

  1. 主用户空间程序将启动内核空间代码(可能通过ioctl)
  2. 用户空间程序并等待内核空间代码
    • kernelspace程序用户空间程序询问输出数据,并 …

c linux driver linux-device-driver linux-kernel

5
推荐指数
1
解决办法
3969
查看次数

计时初始化给出任何指示?

我使用getnstimeofdayconsole_unlock功能,它被初始化过程中很早就叫.如此早,即使计时也不会被初始化以便使用getnstimeofday.

有没有办法确定开始使用的精确时刻getnstimeofday.我的意思是,是否有任何全局变量或任何宏来检查计时是否已初始化,以便我可以开始使用getnstimeofday.

linux kernel timer kernel-module linux-kernel

5
推荐指数
0
解决办法
329
查看次数

无符号整数递增会导致未定义的定义行为吗?

64位读取32位无符号乘法后导致未定义的行为?关于StackOverflow的问题,我开始思考根据C99标准,对小型无符号类型的典型算术运算是否会导致未定义的行为.

例如,请使用以下代码:

#include <limits.h>

...

unsigned char x = UCHAR_MAX;
unsigned char y = x + 1;
Run Code Online (Sandbox Code Playgroud)

x变量被初始化为最大量值unsigned char的数据类型.下一行是问题:值x + 1大于UCHAR_MAX且不能存储在unsigned char变量中y.

我相信以下是实际发生的事情.

  • 该变量x首先被提升为数据类型int(第6.3.1.1/2节),然后x + 1被评估为数据类型int.

假设有一个实现在哪里INT_MAX并且UCHAR_MAX是相同的 - x + 1会导致有符号整数溢出.这是否意味着递增变量x,尽管是无符号整数类型,由于可能的有符号整数溢出会导致未定义的行为?

c c99 undefined-behavior language-lawyer

5
推荐指数
1
解决办法
219
查看次数

将 void * 值设置为 intptr_t 变量是否需要显式转换?

我似乎无法理解当我尝试为变量void *赋值时收到的 GCC 编译器警告intptr_t。具体来说,当我使用 进行编译时-std=c99 -pedantic,我收到以下有关z第 7 行变量初始化的警告:

警告:初始化从指针生成整数而不进行强制转换 [-Wint-conversion]

这是源代码:

#include <stdint.h>

int main(void){
        unsigned int x = 42;
        void *y = &x;

        intptr_t z = y; /* warning: initialization makes integer from pointer without a cast [-Wint-conversion] */

        return 0;
}
Run Code Online (Sandbox Code Playgroud)

当然,如果我明确地转换y为,intptr_t那么警告就会消失。但是,我很困惑为什么隐式转换会出现警告,而隐式转换的全部目的intptr_t在于void *值的转换和操作。

来自C99 标准第 7.18.1.4节:

以下类型指定有符号整数类型,其属性为任何有效的void指针都可以转换为该类型,然后转换回void指针,结果将与原始指针进行比较:

intptr_t

我是否误解了标准,或者在这种情况下,GCC 在“指针中的整数”检查中是否过于迂腐?

c gcc pointers c99 gcc-warning

5
推荐指数
1
解决办法
1833
查看次数

执行x87 FPATAN操作的扩展GCC内联汇编中的clobber列表的说明

以下代码位于MinGW x86inline.h文件中:

/*
** in-line atan2(y,x) function.
** Computes arctan(y/x).
*/
#define atan2(y,x) atan2_x87_inline(y,x)
double atan2_x87_inline(double y,double x);
extern __inline__ double atan2_x87_inline(double y,double x)
    {
    double result;
    __asm__ ("fpatan" : "=t" (result) : "0" (x), "u" (y) : "st(1)");
    return(result);
    }
Run Code Online (Sandbox Code Playgroud)

据我所知,x87 fpatan操作使用st(0)st(1)寄存器,覆盖寄存器的内容st(1),然后弹出顶部寄存器.

那么为什么只st(1)包括在clobber列表中,而不是st(0)呢?

编辑:实际上,它为什么会需要一个撞名单,因为在所有的st(0)st(1)应该知道通过编译器"t""u"约束.是对的吗?

c x86 assembly gcc inline-assembly

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

C预处理器语句是否是C语言的一部分?

我记得我的一位教授在C门课程中提出的主张.他说,#define预处理命令使程序员能够创建在以后的代码使用一个常数,该命令是一个C语言的一部分.

/* Is this truly C code? */
#define FOO 42
Run Code Online (Sandbox Code Playgroud)

由于这是一个介绍性的编程类,我怀疑他只是简化了源文件和编译器之间的关系,但是我希望验证我的理解.

预处理程序语句是否完全独立于C语言(取决于所使用的特定编译器)还是在C99标准中明确描述?出于好奇,K&R曾经提到过预处理器宏吗?

c standards c99 c-preprocessor

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

Linux 内核模块中未执行 CLI 指令

我正在Intel Atom处理器(带有 2 个内核的x86_64)上编写Linux v3.2内核模块。我想禁用特定的 IRQ 编号,但在 Linux 上执行此操作时遇到问题。

我是双引导MS-DOS,通过直接与8259 PIC芯片通信,我可以轻松禁用 Intel 语法 x86 程序集中的中断:

CLI                ; disable all interrupts
MOV    DX, 0x21    ; set 8259 ioport address
IN     AL, DX      ; store current interrupt mask in AL
AND    AL, 0xDF    ; modify mask to disable IRQ 5
OUT    DX, AL      ; send new mask to 8259
STI                ; reenable interrupts
Run Code Online (Sandbox Code Playgroud)

这很有效,我成功地禁用了特定的 IRQ 号码。

Linux 中,我知道我必须使用disable_irq宏来禁用中断,但它似乎没有效果。 …

c x86 assembly interrupt linux-kernel

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

内核空间的RS232串口通信

我正在为Linux v3.2编写内核模块来控制外部激光器,但是我在通过机器上的RS232 串行端口传输信号时遇到了问题。

我的内核中似乎已经编译了一个串行驱动程序,它拥有我想要访问的 ioport 地址的所有权:

# cat /proc/ioports | grep serial
  02e8-02ef : serial
  02f8-02ff : serial
  03f8-03ff : serial
Run Code Online (Sandbox Code Playgroud)

这是有道理的,因为 Linux 允许用户空间程序使用/dev/ttyS*设备节点通过串行端口进行通信。例如,以下是我为 LCD 面板设置设备的方法:

# cat /proc/ioports | grep serial
  02e8-02ef : serial
  02f8-02ff : serial
  03f8-03ff : serial
Run Code Online (Sandbox Code Playgroud)

但是,这是一个用户空间接口,因此与我的内核空间模块不兼容。我需要一种在内核空间内产生相同效果(RS232 串行 I/O)的方法。

虽然我可以卸载默认的 Linux串行驱动程序并用我自己的自定义 RS232 驱动程序替换它,但我不想在这里重新发明轮子——默认的 Linux串行驱动程序似乎支持我需要的功能。

是否有一种简单的方法可以通过内核空间中的 RS232 串行端口进行通信(也许通过这个默认的 Linux串行驱动程序),或者我是否只需要编写自己的自定义 RS232 驱动程序?

serial-port linux-device-driver linux-kernel

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

将unsigned转换为double无符号而不会丢失精度

将整数值转换为浮点值并再次返回与原始整数值相同吗?

例如:

unsigned x = 42;
double y = x;
unsigned z = y;
Run Code Online (Sandbox Code Playgroud)

假设编译器没有优化浮点转换,x == z总是会计算为true

我怀疑浮点转换中的任何表示错误总是会增加值.因此,当浮点值转换回整数值时,将截断该值,该值始终导致原始整数值.

我的假设是否正确?

c floating-point c99 ieee-754 floating-point-conversion

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

在C中,为什么不能声明指针并使其直接指向数字,而不使用malloc?

在C中,为什么X和Y工作但不是Z?

//X     
int num = 5;
int *ptr;
ptr = &num;

//Y
int *mptr = (int *)malloc(sizeof(int *));       
*mptr = 5;       

//Z
int* myptr;
*myptr = 5;
Run Code Online (Sandbox Code Playgroud)

在Z中,我声明一个指针,并尝试使其指向一个数字,但我得到一个分段错误.但在我看来,我在Z和X和Y做同样的事情.在XI中直接使用变量num而不是数字5,而在YI中只使用堆来保存变量而不是堆栈.那么X和Y怎么工作但是Z没有?

c pointers segmentation-fault

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