我是一名嵌入式软件工程师,拥有不到3年的经验.我的目标是不断"磨锯".我想知道C/C++程序员应该熟练掌握低级编程的具体内容.
我想到的是熟悉硬件的架构和指令集.知道如何摆弄位也很重要,资源管理和性能已经成为我工作的一部分,还有什么吗?
编辑:我使用内部定制的RTOS,而不是嵌入式Linux.
我想找到低级C/C++ API,相当于linux系统中的"write",没有缓冲区.有吗?
缓存的I/O如fread,fwrite不是我想要的.
我正在寻找相当于LWARX和STWCX(在PowerPC处理器上找到)或在x86平台上实现类似功能的方法.此外,哪里是最好的地方找到这样的事情(即锁定/等待免费编程的好文章/网站/论坛).
编辑
我想我可能需要提供更多细节,因为我假设我只是在寻找CAS(比较和交换)操作.我要做的是实现一个带有智能指针的无锁引用计数系统,可以通过多个线程访问和更改.我基本上需要一种在x86处理器上实现以下功能的方法.
int* IncrementAndRetrieve(int **ptr)
{
int val;
int *pval;
do
{
// fetch the pointer to the value
pval = *ptr;
// if its NULL, then just return NULL, the smart pointer
// will then become NULL as well
if(pval == NULL)
return NULL;
// Grab the reference count
val = lwarx(pval);
// make sure the pointer we grabbed the value from
// is still the same one referred to by 'ptr'
if(pval != *ptr)
continue;
// Increment … 我正在为无线网卡编写一个相当低级别的驱动程序,虽然大部分规范都相当简单,但我还没有解决一个问题:
如果我的电台处于省电模式且其接收器在DTIM帧之间长时间(例如10秒)关闭,并且同时重新启动接入点,那么我的关联将丢失,我该如何检测到这一点?
我知道最常见的情况是同步丢失得足够彻底,以至于我会错过一些信标,然后简单地回到AP搜索,但如果幸运的话,我会看到信标,是否有一些找出这是同一个AP的新"实例"的方法?
我能想到
作为一个完美主义者,我想知道是否有一种完全可靠的方法可以检测到AP已重新启动,而不仅仅是整理线索.
我目前正在boot.s源代码中读取第一个Linux内核的文件(假设0.01确实是第一个公开发布).
我知道C和ASM,后者比前者少得多.即便如此,我似乎能够理解并基本上掌握源文件中的代码.
这个文件让我很困惑.我现在意识到这是因为它处于实模式,而不是保护模式.不用说,我以前从未见过以实模式编写的ASM代码.保护模式是在我出生之前运行的事实模式x86操作系统,所以这是可以预料的.
这是我想要更好地理解的例程:
/*
* This procedure turns off the floppy drive motor, so
* that we enter the kernel in a known state, and
* don't have to worry about it later.
*/
kill_motor:
push dx
mov dx,#0x3f2
mov al,#0
outb
pop dx
ret
Run Code Online (Sandbox Code Playgroud)
向上看outb,我发现它用于将字节传递给计算机上的端口.我将基于C文档猜测这个场景将"stop motor"字节作为第一个参数传递,并将软盘驱动器端口号作为第二个参数.
这个界面是BIOS提供的吗?还是直接通过软驱?我假设BIOS对所有基本设备的基本操作都有节俭的"驱动程序".
这就是我难倒的地方:似乎数字之类的东西#0x3f2正在被掏出来.它们显然是硬件端口号或其他东西.这个文件上撒有这样的数字,没有解释他们所指的是什么.在哪里可以找到一个全面的参考资料,显示他们可以从实模式接收的所有硬件端口和控制编号?此外,似乎文件在整个启动过程中使用硬编码的内存地址在内存中移动内核.在哪里可以找到有关在实模式下可以写入哪些内存地址范围的指南?
我还阅读了Linus关于重新编程中断的评论,以避免BIOS和内部硬件中断之间的冲突.我不会撒谎,这是我的头脑.
帮助会很棒; 谷歌似乎很少涉及这个话题,万一你想知道.
我发现我们可以从内存地址构建/重建外部指针,请参阅此示例,其中我从数据表对象中获取指针并重建它:
# devtools::install_github("randy3k/xptr")
iris_dt <- data.table::as.data.table(iris)
ptr1 <- attr(iris_dt, ".internal.selfref")
ptr1
#> <pointer: 0x13c00d4e0>
typeof(ptr1)
#> [1] "externalptr"
address <- xptr::xptr_address(ptr1)
address
#> [1] "0x13c00d4e0"
ptr2 <- xptr::new_xptr(address)
identical(ptr1, ptr2)
#> [1] TRUE
Run Code Online (Sandbox Code Playgroud)
显然xptr::new_xptr("0x13c00d4e0")会话之间不稳定,我知道上面没有分配内存而只是定义绑定,这对于我的用例来说很好。
我想对环境做同样的事情:
e <- new.env()
e
#> <environment: 0x10b5bf038>
env("0x10b5bf038") # I want this "env" function
#> <environment: 0x10b5bf038>
Run Code Online (Sandbox Code Playgroud)
我怀疑基础 R 可以做到这一点,所以我对打包选项和 C 魔法持开放态度。
我需要这个用于{constructive} 包,假设我想探索该asNamespace("stats")$.__NAMESPACE__.$DLLs
对象,它的打印方式不是很有帮助:
asNamespace("stats")$.__NAMESPACE__.$DLLs
#> $stats
#> DLL name: stats
#> Filename: /opt/R/4.2.1-arm64/Resources/library/stats/libs/stats.so
#> Dynamic …Run Code Online (Sandbox Code Playgroud) 我找到了这个键盘钩子代码,我试图为我的目的略微修改:http://blogs.msdn.com/toub/archive/2006/05/03/589423.aspx
作为概述,我想让用户按一个键,说'E',并让键盘返回一个不同的字符'Z',对任何焦点的应用程序.
我改变的相关方法现在看起来像:
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
//The truely typed character:
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine((Keys)vkCode);
KBDLLHOOKSTRUCT replacementKey = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
replacementKey.vkCode = 90; // char 'Z'
Marshal.StructureToPtr(replacementKey, lParam, false);
//Now changed to my set character
vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine((Keys)vkCode);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
Run Code Online (Sandbox Code Playgroud)
控制台正确输出为:
E
Z
T
Z
G
Z
etc.
Run Code Online (Sandbox Code Playgroud)
但是,焦点应用程序仍然键入"E"而不是"Z".为什么?我更改了钩子键盘输入以包含'Z'而不是'E',并且控制台线显示它已正确更改!
据我了解,调用return CallNextHookEx(_hookID, nCode, wParam, lParam); …
我的Android应用程序尝试通过访问实际设备(在我的例子中为/ dev/block/vold/179:1)来读取SD卡的物理扇区.(当然,这是在根电话上)
我可以将设备作为a打开FileInputStream,并从中读取数据.但是,我似乎无法读取它超过2GB标记(我的存储卡是16GB).
这是因为Android不支持大于2GB的文件吗?如果是这样的话,为什么函数喜欢position()和skip()接受long参数?
有没有人有关于如何从设备读取超过2GB的建议?
我最近参加了数字逻辑课程并学习了所有关于AND,OR和其他各种逻辑的知识.我们没有涉及的一件事,对编程来说是完全必要的,是if陈述,让我对他们的工作方式感到好奇.
我最好的猜测是它只是一个2:1的多路复用器,当你添加更多else语句时,它会变成4:1和8:1,但对于这样一个简单的概念来说,这似乎有点过于复杂.
任何人都知道一个if声明实际上转化为什么?
我有8个AVX向量,每个向量包含8个浮点数(总共64个浮点数),我想将每个向量中的元素加在一起(基本上执行8个水平求和).
现在,我正在使用以下代码:
__m256 HorizontalSums(__m256 v0, __m256 v1, __m256 v2, __m256 v3, __m256 v4, __m256 v5, __m256 v6, __m256 v7)
{
// transpose
const __m256 t0 = _mm256_unpacklo_ps(v0, v1);
const __m256 t1 = _mm256_unpackhi_ps(v0, v1);
const __m256 t2 = _mm256_unpacklo_ps(v2, v3);
const __m256 t3 = _mm256_unpackhi_ps(v2, v3);
const __m256 t4 = _mm256_unpacklo_ps(v4, v5);
const __m256 t5 = _mm256_unpackhi_ps(v4, v5);
const __m256 t6 = _mm256_unpacklo_ps(v6, v7);
const __m256 t7 = _mm256_unpackhi_ps(v6, v7);
__m256 v = _mm256_shuffle_ps(t0, t2, 0x4E);
const __m256 tt0 = …Run Code Online (Sandbox Code Playgroud)