我正在编写一个简单的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发生之前执行更多代码的事实.
我设想这个工作的方式是:
ioctl)我使用getnstimeofday的console_unlock功能,它被初始化过程中很早就叫.如此早,即使计时也不会被初始化以便使用getnstimeofday.
有没有办法确定开始使用的精确时刻getnstimeofday.我的意思是,是否有任何全局变量或任何宏来检查计时是否已初始化,以便我可以开始使用getnstimeofday.
在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,尽管是无符号整数类型,由于可能的有符号整数溢出会导致未定义的行为?
我似乎无法理解当我尝试为变量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 在“指针中的整数”检查中是否过于迂腐?
以下代码位于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门课程中提出的主张.他说,#define预处理命令使程序员能够创建在以后的代码使用一个常数,该命令是一个C语言的一部分.
/* Is this truly C code? */
#define FOO 42
Run Code Online (Sandbox Code Playgroud)
由于这是一个介绍性的编程类,我怀疑他只是简化了源文件和编译器之间的关系,但是我希望验证我的理解.
预处理程序语句是否完全独立于C语言(取决于所使用的特定编译器)还是在C99标准中明确描述?出于好奇,K&R曾经提到过预处理器宏吗?
我正在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宏来禁用中断,但它似乎没有效果。 …
我正在为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 驱动程序?
将整数值转换为浮点值并再次返回与原始整数值相同吗?
例如:
unsigned x = 42;
double y = x;
unsigned z = y;
Run Code Online (Sandbox Code Playgroud)
假设编译器没有优化浮点转换,x == z总是会计算为true?
我怀疑浮点转换中的任何表示错误总是会增加值.因此,当浮点值转换回整数值时,将截断该值,该值始终导致原始整数值.
我的假设是否正确?
在C中,为什么X和Y工作但不是Z?
//X
int num = 5;
int *ptr;
ptr = #
//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没有?