我一直在为ARM的嵌入式操作系统工作,但是即使在引用ARMARM和linux源代码之后,我仍然对架构有一些了解.
原子操作.
ARM ARM表示加载和存储指令是原子的,并且在执行中断处理程序之前保证其执行完整.通过查看验证
arch/arm/include/asm/atomic.h :
#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
Run Code Online (Sandbox Code Playgroud)
但是,当我想使用对于ARMv7(我的目标)使用LDREX和STREX的cpu指令(atomic_inc,atomic_dec,atomic_cmpxchg等...)原子地操作此值时,问题就出现了.
ARMARM没有说明在本节中阻止中断的任何内容,因此我假设在LDREX和STREX之间可能发生中断.它提到的事情是关于锁定内存总线,我猜这只对MP系统有帮助,因为MP系统可能有更多的CPU试图同时访问同一个位置.但对于UP(可能还有MP),如果在LDREX和STREX的这个小窗口中触发定时器中断(或SMP的IPI),异常处理程序执行可能会更改cpu上下文并返回到新任务,但是令人震惊的部分现在进入,它执行'CLREX',因此删除前一个线程持有的任何独占锁.那么在UP系统上使用LDREX和STREX比LDR和STR在原子性方面有多好?
我确实读过一些关于独占锁监视器的东西,所以我有一个可能的理论,当线程恢复并执行STREX时,os监视器会导致此调用失败,可以检测到并且可以使用new重新执行循环过程中的价值(分支回LDREX),我在这里吗?
一点介绍,
我目前正在编写一个小的(读取微小的)RTOS内核,它应该与内核中的大多数内容单片.但是我找不到下面列出的一些事情的很多信息,这将是非常有用的,除此之外,它实际上不是某种大学项目,而是我正在按照自己的意愿行事.
回答所有问题的一个更好的选择是,如果你可以向我推荐一个免费提供的RTOS(甚至免费书籍),最好是实现用户空间并且是可抢占的(但不像linux那样复杂).Linux有一些我迄今为止看过的最糟糕的文档(我确实尝试过从linux代码中解决问题,但是只有大量的定义分散在一百万个文件和函数钩子中,并且有很多名字,每个版本都会重命名有时感动...)
"抢占"和"上下文切换"有什么区别?
抢占式和非抢占式内核之间的主要区别是什么?程序员需要做什么工作才能使内核抢占先机?
如何创建和使用用户模式?
ARM文档说,在用户模式下,任何切换到特权模式的指令都将被视为未定义指令.
如果是这样,用户空间程序使用内核代码的唯一方法是系统调用?
内核如何响应用户空间或与之交互?
这是否意味着启动后(在一个简单的系统中)唯一的内核线程将是空闲线程?
如果在切换到用户进程时取消映射内核代码和数据所在的页面,那么在系统调用或中断时,内核代码如何在不映射到虚拟地址空间的情况下执行?
"可抢占的内核"是否仅仅意味着内核的设计方式使得在执行内核代码期间进行上下文切换是安全的?或者它是否需要做更多的工作?
哦,如果这里不允许这么多问题,抱歉,找不到任何相关的内容.
这部分gcc手册非常模糊,我无法理解重复尝试后forceinline属性的用法.
我正在定义一个对象和某些函数来操纵该对象.这些函数中很少有可以使用原子指令,我希望编译器内联这些函数.但是,我不想在头文件中编写这些函数,并在Linux内核中使用"静态内联"声明它们.
有没有办法强制gcc从另一个翻译单元内联函数?
在嵌套循环中打破时会发生什么?
假设以下代码:
for(int x = 0; x < 10; x++)
{
do {
if(x == 4)
break;
x++;
} while(x != 1);
}
Run Code Online (Sandbox Code Playgroud)
遇到break语句,for循环或do while循环时哪个循环会退出?
这个问题已经回答了x86然而,我找不到很多关于ARM MP cpus如Cortex-A9,Cortex-A15等...
更重要的是,我想知道是否可以在非主cpu上引发中断而无需任何配置等.
我正在研究一个只处理主CPU的软件,因此我将其余部分置于WFI状态,但是我不知道MP arm cpus上的中断是如何工作的,主cpu是否可能继续执行代码和其中一个cpu选择它并跳转到向量表中的指令并执行该代码?
顺便说一下这是我用来将它们置于低功耗模式的代码
uint32_t reg;
__asm__ volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (reg));
reg &= 0xF;
if(reg > 0)
goto spin;
<code snipped>
spin:
for(;;)
cpu_idle(); // cpu_idle -> wfi
Run Code Online (Sandbox Code Playgroud) 好吧,不幸的是我在一个二进制数据部分点击了'C'我已经工作了很多并保存它,因为我有很多未保存的工作.我尝试将这个巨大的部分转换回数据,但每当我选择行并按'D'时,只有光标所在的行被转换为数据.
所以,我的问题是,如何在IDA中标记/转换大量数据到代码(特别是6.1)
(如果重要的话,目标架构是ARM).
我已经阅读了很长一段时间,但对我来说没有意义.可能是因为我对这一切都是新手,但仍然不了解很少的内核概念.
这就是我提出的(没有错误或NULL处理,这只是为了问题):
内核螺旋锁在内核线程中执行,这是预先设置的.
void spinlock_acquire(spinlock_t *spinlock)
{
tryagain:
while(spinlock->plock != UNLOCKED) ;
context_switch_block;
if(spinlock->plock != UNLOCKED) {
context_switch_unblock;
goto tryagain;
}
spinlock_lock(spinlock, current_thread);
context_switch_unblock;
}
Run Code Online (Sandbox Code Playgroud) 我一直在使用一个程序,使用GCC 4.4.1(ISO C99)编译并且今天注意到了这个怪癖.虽然它在目标上运行没有任何问题,但编译器也不会使用-Wall发出任何警告.
void mutex_init(mutex_t *mutex)
{
if(unlikely(mutex->magic == MUTX_MAGIC_CHAR))
return;
mutex->owner = NULL;
mutex->prior = NULL;
mutex->magic = MUTX_MAGIC_CHAR;
thread_queue_init(&mutex->queue);
}
Run Code Online (Sandbox Code Playgroud)
不应该是这样的
*mutex->owner = NULL;
Run Code Online (Sandbox Code Playgroud)