---
tags: linux2022
---
# 2022q1 Homework1 (quiz1)
contributed by < `bebo1010` >
## AAA
```
(a) /* no operation */
(b) n->pprev = first
(c) n->next = first
(d) n->pprev = n
```
首先我注意到一件事情,(b)和(d)是不可選的選項
pprev 是指標的指標,而 first 和 n 的型態是指標
因此填入(b)和(d)會發生編譯器報錯的問題
接下來我檢查了程式碼,了解缺失的部分就是把新增的 n 放入 list 的步驟
因此`AAA`和`BBB`必定填入`n->next`以及`n->pprev`相關的 code
由於已經有兩個選項遭到刪去,剩下的`n->next = first`就是唯一解
## BBB
```
(a) n->pprev = &h->first
(b) n->next = h
(c) n->next = n
(d) n->next = h->first
(e) n->next = &h->first
```
接續AAA的作答思路,AAA已經填入`n->next = first`後
BBB應該要填入`n->pprev`有相關的 code
因此直接選(a)回答
## trace code 時注意到的東西
當下在讀這份程式碼時,我注意到了 hash 的方式,這種 hash 的方式我從來沒有看過的
```c
#define GOLDEN_RATIO_32 0x61C88647
static inline unsigned int hash(unsigned int val, unsigned int bits) {
/* High bits are more random, so use them. */
return (val * GOLDEN_RATIO_32) >> (32 - bits);
}
```
`quiz1`這份 code 的 hash 形式是把輸入的值乘上`GOLDEN_RATIO_32`後再向右位移 $32-x$ 個 bits
之後我也去大致翻了一下 linux 的 hash 作法 [link](https://elixir.bootlin.com/linux/v4.7/source/fs/btrfs/btrfs_inode.h#L222)
``` c
static inline unsigned long btrfs_inode_hash(u64 objectid,
const struct btrfs_root *root)
{
u64 h = objectid ^ (root->objectid * GOLDEN_RATIO_PRIME);
#if BITS_PER_LONG == 32
h = (h >> 32) ^ (h & 0xffffffff);
#endif
return (unsigned long)h;
}
```
這個 hash 做法又跟`quiz1`內提到的不太相同,但是我也說不上這是什麼寫法
我自己在上學期作業系統的作業內寫過一種 hash
```c
struct dummy * db_hash(char *key)
{
//my hash function, just mod a prime number
int hash_value = 0;
if(key[1] == '\0' && key[0] == '\0')
hash_value = 0;
if(key[1] != '\0' && key[0] == '\0')
hash_value = (int) key[1];
if(key[1] == '\0' && key[0] != '\0')
hash_value = (int) key[0];
if(key[1] != '\0' && key[0] != '\0')
hash_value = (int) (key[0] * key[1]);
hash_value = hash_value % DB_LENGTH; //DB_LENGTH = 251
return &db[hash_value];
}
```
這做法是把輸入(預設輸入都是字串)的前兩個字元做`ASCII code`的對應數值相乘後再對預先設定好的 hash table 長度(預先取一個質數)做模除運算
或許我的做法有點冗餘,但我認為整體來說和 linux 的做法可以互相比較一下
可是我不太確定這兩種做法間有什麼實質上的差別(扣除我的 code 寫得太過冗長以外)
或許教授和助教在改這份時可以給我點意見