给定数据段中找到第一个有效bit实现(文件系统)

查找空闲inode方法
本文介绍了Linux内核中用于查找文件系统空闲inode的方法。详细解释了find_first_zero_bit_le和find_first_zero_bit函数的工作原理,并展示了一种有趣的C语言实现来定位最近的有效位。

文件系统中查找,空闲inode时候需要用到

一个每个文件系统都有自己的实现(如minix),现在kernel中统一调用这个:

static inline unsigned long find_first_zero_bit_le(const void *addr,
  unsigned long size)
{
 return find_first_zero_bit(addr, size);
}

找到最近的一个还有有效bit的字:

unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
{
	const unsigned long *p = addr;
	unsigned long result = 0;
	unsigned long tmp;

	while (size & ~(BITS_PER_LONG-1)) {
		if (~(tmp = *(p++)))
			goto found;
		result += BITS_PER_LONG;
		size -= BITS_PER_LONG;
	}
	if (!size)
		return result;

	tmp = (*p) | (~0UL << size);
	if (tmp == ~0UL)	/* Are any bits zero? */
		return result + size;	/* Nope. */
found:
	return result + ffz(tmp);
}

在一个字里面找有效bit的位置,这个方法kernel中有很多实现,其中大部分是

直接用汇编实现的(当然也大部分看不懂),其中有个c语言实现很有意思(一个字里面还用上了二分差查找)

/**
 * __ffs - find first bit in word.
 * @word: The word to search
 *
 * Undefined if no bit exists, so code should check against 0 first.
 */
static __always_inline unsigned long __ffs(unsigned long word)
{
	int num = 0;

#if BITS_PER_LONG == 64
	if ((word & 0xffffffff) == 0) {
		num += 32;
		word >>= 32;
	}
#endif
	if ((word & 0xffff) == 0) {
		num += 16;
		word >>= 16;
	}
	if ((word & 0xff) == 0) {
		num += 8;
		word >>= 8;
	}
	if ((word & 0xf) == 0) {
		num += 4;
		word >>= 4;
	}
	if ((word & 0x3) == 0) {
		num += 2;
		word >>= 2;
	}
	if ((word & 0x1) == 0)
		num += 1;
	return num;
}



 

<think>好的,我现在需要解决用户的问题:在嵌入式系统中,如何对变量a的bit3进行置位和清除,同时保持其他位不变。用户还要求写出两段代码来实现这两个操作。 首先,我得回顾一下位操作的基本知识。在C语言中,位操作通常使用位运算符,比如按位或(|)、按位与(&)、按位取反(~)等。对于置位某个位,通常的做法是使用按位或运算,因为无论该位原来的值是0还是1,与1进行或运算后都会变成1。而清除某个位则需要用按位与运算,将目标位设为0,其他位保持1,这样与原来的值进行与运算时,其他位不变,目标位被清零。 接下来需要确定bit3的位置。这里需要注意,通常位编号是从0开始的,所以bit3对应的是第4位,即2的3次方,也就是8(0x08)。不过有时候可能存在不同的位编号习惯,比如有的系统可能从1开始计数,但根据常见的嵌入式编程实践,应该是从0开始,所以bit3对应的是第3位,即8(0x08)。需要确认这一点是否正确,避免错误。 然后考虑置位操作。置位bit3应该使用或运算,将变量a与一个只有bit3为1的掩码进行或操作。例如,a |= (1 << 3)。这样无论原来的bit3是0还是1,都会被设置为1,其他位不变。 接下来是清除操作。清除bit3需要使用与运算,将变量a与一个除了bit3为0外其他位都为1的掩码进行与操作。例如,a &= ~(1 << 3)。这里的按位取反运算符会将1 << 3的结果(0x08)变为0xF7(假设是8位的情况),这样与原来的a进行与操作时,bit3会被清零,其他位保持不变。 需要确认这两个操作是否正确。对于置位,假设a原来的bit3是0,执行后变为1;如果原来是1,保持1。对于清除,无论原来是0还是1,执行后都会变成0。其他位确实不受影响,因为掩码中其他位都是1(在置位时)或0(在清除时?不对,清除时掩码除了bit3外都是1,所以与操作后其他位保持原样)。 另外,要考虑数据类型的宽度。比如,如果a是32位的整型,那么1 << 3会得到0x00000008,而取反后是0xFFFFFFF7。这样在与a进行与操作时,高位不会被截断,确保所有位都被正确处理。如果使用不同的整型,如16位或8位,可能需要显式转换,但一般来说,C语言会自动处理这些情况,只要操作数和变量的类型匹配。 用户可能是在嵌入式开发中遇到的实际问题,比如配置寄存器时需要设置或清除某个特定的位而不影响其他位。这时候正确的位操作非常重要,因为错误的操作可能导致寄存器其他位被意外修改,引发硬件错误。 可能需要提醒用户注意位编号的问题,确保他们确实是要操作bit3,而不是其他位。此外,还可以建议使用宏定义或者常量来替代魔数,提高代码的可读性和可维护性。例如: #define BIT3_MASK (1 << 3) a |= BIT3_MASK; // 置位 a &= ~BIT3_MASK; // 清除 这样在代码中更容易理解,也方便后续修改。 最后,检查代码是否有语法错误,比如分号是否正确,操作符是否正确使用。确保示例代码能够直接运行,不会有遗漏或者错误。</think>以下是针对嵌入式系统位操作的实现方法,保持其他位不变的前提下操作bit3: --- ### **核心原理** - **置位(Set)**:使用 `|` 运算将目标位强制为1 - **清除(Clear)**:使用 `&` 和 `~` 运算将目标位强制为0 --- ### **代码实现** #### **1. 置一bit3(设为1)** ```c // 方法1:直接位操作 a |= (1 << 3); // 等价于 a = a | 0x08 // 方法2:使用宏定义提高可读性 #define BIT3_MASK (1 << 3) a |= BIT3_MASK; ``` #### **2. 清除bit3(设为0)** ```c // 方法1:直接位操作 a &= ~(1 << 3); // 等价于 a = a & 0xF7(假设8位系统) // 方法2:使用宏定义提高可读性 #define BIT3_MASK (1 << 3) a &= ~BIT3_MASK; ``` --- ### **详细解释** | **操作** | **运算符** | **逻辑** | |-----------|------------|--------------------------------------------------------------------------| | 置位 | `|=` | 将 `bit3` 对应的掩码(0x08)与原值按位或,强制该位为1,其他位保留原值 | | 清除 | `&=` + `~` | 将 `bit3` 掩码取反后(0xF7)与原值按位与,强制该位为0,其他位保留原值 | --- ### **验证示例** ```c #include <stdio.h> int main() { unsigned int a = 0x00; // 初始值:0000 0000 // 置位bit3 a |= (1 << 3); printf("置位后: 0x%02X\n", a); // 输出0x08 (0000 1000) // 清除bit3 a &= ~(1 << 3); printf("清除后: 0x%02X\n", a); // 输出0x00 (0000 0000) return 0; } ``` --- ### **关键注意事项** 1. **位编号规则**: - **bit0** 是最低位(右侧第1位),**bit3** 是第4位(从0开始计数) - 对应掩码值: $$ 1 \ll 3 = 8_{10} = 0x08_{16} $$ 2. **数据类型兼容性**: - 若 `a` 为 8位类型(如 `uint8_t`),掩码为 `0x08` - 若 `a` 为 32位类型(如 `uint32_t`),掩码为 `0x00000008` 3. **原子操作**: 在嵌入式系统中,若涉及对硬件寄存器的操作,需确保使用**原子操作**(如CMSIS库的 `__atomic` 函数)防止中断干扰。 --- ### **最佳实践** - **使用宏或枚举定义位掩码**: ```c #define BIT3_POS (3) // bit3的位置 #define BIT3_MASK (1 << BIT3_POS) ``` - **注释明确作用**: ```c a |= BIT3_MASK; // 启用bit3功能 a &= ~BIT3_MASK; // 禁用bit3功能 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值