以下无法编译:
typedef int arr[10];
int main(void) {
return sizeof arr;
}
sizeof.c:3: error: expected expression before ‘arr’
Run Code Online (Sandbox Code Playgroud)
但如果我改成它
sizeof(arr);
Run Code Online (Sandbox Code Playgroud)
一切都好.为什么?
在gcc中,我可以写foo ? : bar
一下这是一种速记形式,foo ? foo : bar
但我看到K&R没有提到它.
这是我应该依赖的东西,在某些标准中定义了吗?或者只是一个(邪恶的)gcc扩展我应该避免?
我正在开发一个嵌入式Linux项目,它将ARM9连接到硬件视频编码器芯片,并将视频写入SD卡或USB记忆棒.软件体系结构涉及将数据读入缓冲池的内核驱动程序,以及将数据写入已安装的可移动设备上的文件的用户空间应用程序.
我发现超过一定的数据速率(大约750kbyte/sec),我开始看到用户视频写入应用程序停止大约半秒钟,大约每5秒钟.这足以导致内核驱动程序用完缓冲区 - 即使我可以增加缓冲区的数量,视频数据也必须与实时进行的其他事情同步(理想情况下在40ms内).在这5秒的"滞后峰值"之间,写入在40ms内完成(就应用程序而言 - 我很欣赏它们被OS缓冲)
我认为这种滞后峰值与Linux将数据刷新到磁盘的方式有关 - 我注意到pdflush旨在每5秒唤醒一次,我的理解是这将是写作的内容.一旦停止结束,用户态应用程序就能够快速服务并写入积压的缓冲区(没有溢出).
我认为我写的设备具有合理的最终吞吐量:从内存fs复制15MB文件并等待同步完成(并且usb棒的灯停止闪烁)给了我大约2.7MBytes/sec的写入速度.
我正在寻找两种线索:
如何阻止突发性写入停止我的应用程序 - 可能是进程优先级,实时补丁,或调整文件系统代码以连续写入而不是匆忙写入?
如何让我的应用程序了解文件系统在写入积压和卡/棒的吞吐量方面发生了什么?我能够动态地改变硬件编解码器中的视频比特率,这比丢帧更好,或者在最大允许比特率上强加一个人工上限.
更多信息:这是一个200MHz ARM9,目前运行基于Montavista 2.6.10的内核.
更新:
我希望这是有道理的.stackoverflow上的第一个嵌入式Linux问题?:)
这可能不寻常,所以让我设置场景:
我们有一个SVN repo,包含我们的项目历史 - 一个基于Linux的嵌入式系统.SVN repo包含Linux内核,U-Boot,busybox等源以及我们所有的内部应用程序,文件系统等.
我们拥有的Linux内核已经老旧而且我正在努力移植到主线,主线正在积极开发我们的平台.我正在git下进行内核方面的工作,并与"社区"交换补丁.
我可以让事情工作并获取内核源代码的快照并将其转储到SVN中,但我希望能够获得更新,拥有本地分支并使用git管理补丁.我可以保留两个内核副本,一个由每个SCM管理,但这有点乱.使用git管理的内核源进行开发和测试也存在风险,并且忘记将这些更改放入SVN导致SVN版本损坏,其中非内核源不同步.
将整个项目迁移到git不是一种选择.使用git管理内核源代码并在SVN中使用一堆粘合脚本和存储的哈希是可能的,但是对于整个项目来说,从SVN获得统一的历史/差异化能力会更好.
我正在考虑的是尝试在同一目录中同时管理SVN和git下的内核源代码.
作为内核开发人员,我主要使用git并在事情看起来很好的时候做内部使用的SVN提交.对于其他内部用户,他们可以通过一个SVN签出获得整个一致的源,查看统一的历史记录,他们可以在SVN下对内核源进行更改.后来我或其他git-using人可以SVN更新这些更改并将它们提交给适当的git.
一些有趣的方法是让git忽略.svn文件,反之亦然.另外我不太确定如何使用普通的SVN结账并告诉git开始管理内核子树,但我确定git有一些不起眼的瑞士军刀选项来做到这一点.
所以这就是我的想法.这意味着大多数同事不必担心git,我们可以根据需要悄悄地忽略git和fork.
这里的问题确实是,有没有人做过这样的事情,它是如何运作的,或者你提出了什么替代解决方案?
我想编写一个宏来编写一个字符串,使用编译时优化知道字符串文字的长度.但我需要使用指针检测误用.
这就是我的意思:
void transmit(const char *data, int length);
#define tx_string(x) transmit((x), sizeof(x) -1)
void func(char *badmsg) {
tx_string("GO"); // ok
tx_string(badmsg); // not OK
}
Run Code Online (Sandbox Code Playgroud)
使用第二个调用时,大小将是无意义的(指针的大小).
如果我尝试在除字符串文字之外的任何内容上使用tx_string,我想产生编译时错误.这是使用gcc; 我可以使用一些gcc的东西吗?
编辑:我使用可能包含空值或不由空值终止的数据缓冲区.我真的想防止指针被用于此,并防止运行时strlen()
使用.
编辑2:
这是一个会导致问题的例子.我将发明一个假想的协议,我必须使用命令GO后跟地址为16位原始(两个8位字符)告诉16位微控制器一个地址,我想从地址0开始.
#define GOSEQ "GO\000\000"
void func(void) {
char *bad = GOSEQ;
tx_string(GOSEQ); // ok, sends 4 bytes: GO and two zero bytes
tx_string(bad); // bad, using runtime strlen sends two characters "GO"
}
Run Code Online (Sandbox Code Playgroud)
我确信必须有某种gcc内置检查.我看到Linux内核源代码使用了这样的编译时区分技巧..但是不能快速地将手放在特定的一个上面.
到目前为止,"Windows程序员"的想法看起来不错,但更有意义的编译时错误将是一个奖励.
我有一个trace()
宏我用另一个宏打开和关闭,例如
#ifdef TRACE
#define trace(x) trace_val(x, 0)
#else
#define trace(x) 0
#endif
Run Code Online (Sandbox Code Playgroud)
warning: statement with no effect
当我trace()
用TRACE
undefined 调用时,这是从gcc 生成的.经过一番搜索,我发现了变化
#define trace(x) 0
Run Code Online (Sandbox Code Playgroud)
至
#define trace(x) (void)0
Run Code Online (Sandbox Code Playgroud)
沉默错误.我的问题是:为什么?有什么不同?
我正在研究一种嵌入式Linux视频录像机应用程序,它将MP4格式视频写入文件(在FAT格式SD卡上).
一些复杂因素是视频和音频数据来自硬件编解码器,必须以低延迟进行服务,并且必须写入支持DMA的缓冲区.
对于输出文件,我使用open()和write(),但发现write()在系统负载时可能需要几百毫秒才能返回,所以我的写入是在一个单独的线程中完成的.
我将数据从(小的,有限数量的)DMA缓冲区复制到一个多兆字节的malloc循环缓冲区,然后从另一个线程中的write()复制数据.这意味着我至少要做两次拷贝,一次进入app缓冲区,一次进入系统缓冲区缓存.
我正在考虑尝试O_DIRECT写入以避免副本,但我对任何评论感兴趣.我注意到Robert Love 评论说O_DIRECT很糟糕,但没有说明原因.
另一方面,如果有人知道如何让write()在很长一段时间内没有停止(AIO?),我也会感兴趣,然后我可以像Linus那样使用缓冲区缓存.
这个问题与我关于写档的问题无关.
我正在考虑嵌入式Linux项目中即将出现的情况(还没有硬件),其中两个外部芯片需要共享一条物理IRQ线.该线路能够用于边沿触发的硬件,但不能用于电平触发的中断.
看看Linux中的共享irq支持,我理解这对两个独立驱动程序的工作方式是每个驱动程序都会调用它们的中断处理程序,检查它们的硬件并在适当的时候处理.
但是我想象下面的竞争条件,并且想知道我是否遗漏了某些东西或者可以做些什么来解决这个问题.假设有两个外部中断源,设备A和B:
似乎要解决这个问题,核心中断处理程序必须在运行所有处理程序后检查IRQ级别,如果仍然处于活动状态,则再次运行它们.Linux会这样做吗?我不认为中断内核知道如何检查IRQ线的电平.
这场比赛是否真的会发生,如果是这样,我该怎么处理?
我有一个(C,Linux)应用程序通过关闭来处理Ctrl-C SIGINT.我想补充的另一个信号处理程序,这样我可以"运行时重新加载配置"使用其他的按键组合进行.
所以我从一个信号看起来我可以通过击键发送到前台进程,这不会强制进程退出或挂起.还有其他人吗?
我一直在研究一个多线程C(Linux)应用程序 - 一个录像机,它有线程用于音频和视频捕获,编码,多路复用和写入.
我开始使用pthread操作临时将它放在一起,但是现在我正在尝试扩展它以支持更多状态并重构代码块,这些代码块与锁定,设置标志和发出条件信号重复出现,以及等等.
到目前为止,我想出的是这样的:
我打算将公共元素存储在一个结构中,并有一个结构数组,我可以循环来启动,检查和停止所有线程.
由于这变成了一个更通用的线程支持模型,我以为我可能会重新发明轮子,所以我会问这里是否应该应用一些众所周知的模式.