来自GNU C编程教程:
该
fgets("文件中获取字符串")功能类似于获取功能.这个函数已被弃用 - 这意味着它已经过时,强烈建议你不要使用它 - 因为它很危险.这很危险,因为如果输入数据包含空字符,则无法分辨.fgets除非您知道数据不能包含null,否则请勿使用.不要使用它来读取用户编辑的文件,因为如果用户插入空字符,您应该正确处理它或打印清晰的错误消息.如果可以,请始终使用getline或getdelim代替fgets.
我觉得这个fgets功能在遇到a \0或者时会停止\n; 为什么当fgets应该正确处理输入时,这个手册页建议空字节是"危险的" ?此外,之间有什么区别getline和fgets,是fgets真正视为功能过时的C99或将来的C标准?
假设以下初始化:
char mystr[4] = "";
Run Code Online (Sandbox Code Playgroud)
C99标准是否保证初始化为空字符串的字符数组会将字符数组中的所有元素初始化为空字节?例如,标准是否保证mystr[2] == '\0'?
这些初始化如何:
char myfoo[4] = { '\0' };
char mybar[4] = { 0 };
Run Code Online (Sandbox Code Playgroud)
虽然我敢肯定,明确设置的字符数组的第一个元素将保证元素的其余部分的隐式初始化0,我怀疑在复制到阵列的字符串字面量初始化结果-从而意味着一个单一的 \0复制到阵列,而其余元素保持未初始化.
我想定义一个多维C字符串数组,该数组由多个字符串文字初始化。在C语言中,我将执行以下操作:
#include <stdio.h>
const char *strArr[2][1] = { {"foo"}, {""}};
int main(void) {
printf("%p\t%p\n", strArr[0][0], strArr[1][0]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在以下位置编译gcc -std=c18 -pedantic test.c并执行结果:
#include <stdio.h>
const char *strArr[2][1] = { {"foo"}, {""}};
int main(void) {
printf("%p\t%p\n", strArr[0][0], strArr[1][0]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如我所料,空字符串文字strArr[1][0]会衰减为有效的指针。
但是,当我在C ++中尝试相同的代码时:
#include <cstdio>
const char *strArr[2][1] = { {"foo"}, {""}};
int main(void) {
printf("%p\t%p\n", strArr[0][0], strArr[1][0]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在以下位置编译g++ -std=c++17 -pedantic test.cpp并执行结果:
$ ./a.out
0x55d95410f004 0x55d95410f008 …Run Code Online (Sandbox Code Playgroud) 假设我有一个示例源文件test.c,我正在编译它:
$ gcc -03 -Wall
test.c看起来像这样..
/// CMP128(x, y)
//
// arguments
// x - any pointer to an 128-bit int
// y - any pointer to an 128-bit int
//
// returns -1, 0, or 1 if x is less than, equal to, or greater than y
//
#define CMP128(x, y) // magic goes here
// example usages
uint8_t A[16];
uint16_t B[8];
uint32_t C[4];
uint64_t D[2];
struct in6_addr E;
uint8_t* F;
// use CMP128 on any combination of pointers …Run Code Online (Sandbox Code Playgroud) 获取struct classLinux内核模块中现有设备类()的指针
大家好!
我正在尝试在现有设备类中注册设备,但是我无法获取指向现有类的指针.内核版本是Linux 3.3.6.我可以在模块中创建一个类,获取指向它的指针,然后使用它来注册设备:
*cl = class_create(THIS_MODULE, className);
dev_ret = device_create(*cl, NULL, *dev, NULL, driverName);
Run Code Online (Sandbox Code Playgroud)
但是,我需要在同一个类中注册另一个设备与另一个模块,但我找不到一种方法来获取指向现有类的指针.我不能在另一个模块中再次创建类,因为类已经存在,class_create返回NULL而不是指向所需类的指针device_create.我找到了:
http://lwn.net/Articles/102500/
一个函数,通过名称返回指向类的指针:
struct class * class_find(char * name)
Run Code Online (Sandbox Code Playgroud)
但是当我尝试编译函数时,编译器说它不存在.我以为这个函数是由内核导出的(我的模块有许可证GPL),但似乎不是.也许我需要包含一些标题?
我试图重写这个函数,因为它的代码是上面链接中的列表.但是当我尝试迭代class_subsys时:
list_for_each_entry(this_class, &class_subsys.kset.list, subsys.kset.kobj.entry)
Run Code Online (Sandbox Code Playgroud)
现在class_subsys没有找到符号.我再次认为它被导出到内核.
我不确定缺少什么.一些头?我这样做是错误的吗?还有另外一个功能吗?
我想如果我可以sysfs从头开始遍历,我可以获得指向现有类的指针.但我也没有找到如何开始遍历sysfs.我见过的所有函数都需要指向kobject或kset开始遍历的指针.但我甚至没有指针sysfs或内核对象的根,所以我不能开始遍历树来获取类指针.
有人能指出我正确的方向吗?
我试图在内核驱动程序和用户空间程序之间异步通信(我知道这里有很多问题需要类似的信息,但我找不到任何处理sysfs_notify的问题).
我将离开Vilhelm的编辑,但是将源添加到使用sysfs的简单驱动程序和用户空间程序进行轮询.驱动程序工作正常(我从网上得到了大部分;它缺少了学分,但是当我回去添加它们时我找不到它们).不幸的是,投票计划不起作用.它总是立即返回成功.有趣的是,如果我在轮询之前不执行两次读取,则revents成员将设置为POLLERR | 如程序输出中所见,POLLIN而不仅仅是POLLIN.
节目输出:
root @ ubuntu:/ home/wmulcahy/demo#./ readhello
triggered
属性文件值:74(t)[0]
revents [0]:00000001
revents [1]:00000001
这是驱动程序:hello.c(你可以看到我开始的地方......)
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
struct my_attr {
struct attribute attr;
int value;
};
static struct my_attr notify = {
.attr.name="notify",
.attr.mode = 0644,
.value = 0,
};
static struct my_attr trigger = {
.attr.name="trigger",
.attr.mode = 0644,
.value = 0,
};
static struct attribute * myattr[] = {
¬ify.attr,
&trigger.attr,
NULL
};
static ssize_t show(struct kobject *kobj, …Run Code Online (Sandbox Code Playgroud) 假设如下:
unsigned char foo = 3;
unsigned char bar = 5;
unsigned int shmoo = foo + bar;
Run Code Online (Sandbox Code Playgroud)
是否保证将值foo和bar值提升为int表达式评估的值foo + bar- 或者是否允许实现它们的实现unsigned int?
在第6.2.5节第8段中:
对于具有相同签名和不同整数转换等级的任何两个整数类型(参见6.3.1.1),具有较小整数转换等级的类型的值范围是另一种类型的值的子范围.
在第6.2.5节第9段中:
如果a
int可以表示原始类型的所有值,则该值将转换为int; 否则,它被转换为unsigned int.
保证具有较小整数转换等级的整数类型具有作为另一类型的值的子范围的值的范围似乎取决于整数类型的有符号性.
signed char 对应于 signed intunsigned char 对应于 unsigned int这是否意味着a的值unsigned char只能保证在子范围内unsigned int而不一定int?如果是这样,那是否意味着一个实现理论上可以有一个unsigned char不在a的子范围内的值int?
如果将枚举对象设置为不等于其任何相应枚举常量的值,则枚举对象具有什么值?
请考虑以下代码:
enum foobar{
FOO = 1,
BAR = 5
};
enum foobar baz = 5;
enum foobar qux = 42;
Run Code Online (Sandbox Code Playgroud)
变量baz设置为整数值5,而变量qux设置为整数值42.
我怀疑该变量baz将保留该值BAR,但我不确定该变量qux.没有为枚举常量赋值42,那么当enum foobar变量设置为这样的值时会发生什么?
是C99的标准明确患得患失?
我正在编写一个简单的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)我正在在线阅读Linux 设备驱动程序第 3 版书籍,但在理解原子变量的初始化宏时遇到问题:
static atomic_t foobar = ATOMIC_INIT(1);
Run Code Online (Sandbox Code Playgroud)
我查看了Linux kernel v3.2的源代码,但我只提出了两个定义:
#define ATOMIC_INIT(i) { (i) }
Run Code Online (Sandbox Code Playgroud)
和
#define ATOMIC_INIT(i) ((atomic_t) { (i) })
Run Code Online (Sandbox Code Playgroud)
宏定义的第二个版本似乎在功能上与第一个版本相同——事实上,当值无论如何都会隐式转换为 时,即使进行显式转换似乎也是多余的atomic_t。为什么有两个版本的定义?
ATOMIC_INIT如果atomic_tLinux 内核的未来版本中的结构发生变化,宏的目的是否只是为了防止代码中断?