2012年8月26日 星期日

[LINUX] 在ubuntu環境編譯 skull 的方法

編譯LDD3書上範例 skull時,遇到了一些問題,茲記錄如下:

程式碼範例下載:http://www.oreilly.com.tw/product_linux.php?id=a184
測試機器編譯環境:Linux 3.2.0-23-generic #36-Ubuntu SMP

書上的範例是適用於 Linux 2.4/2.6 版本的,因此在 3.2.0-23 核心下編譯會造成許多錯誤訊息,以下針對scull的編譯錯誤作一整理說明。

1. 缺少linux/config.h,
原因:因為 config.h 在 linux kernel 2.6.19已經拿到 config.h
改法:有兩種方式
a. 在檔案內直接註解 #include <linux/config.h>
b. 自行建立一個空的檔案,例如執行下列命令
touch /usr/src/linux-headers-`uname -r`/include/linux/config. 
同樣類似的問題還有 #include ,建議直接註解這兩個 include

2. scripts/Makefile.build:49: *** CFLAGS was changed in "/home/albert/examples/scull/Makefile". Fix it to use ccflags-y. Stop.
改法:有兩種方式:
a. CFLAGS -> EXTRA_CFLAGS
b. make KBUILD_NOPEDANTIC=1


3. 錯誤: 初始值設定項裡有不明的欄位 「ioctl」
linux內核到2.6.36之後把ioctl這個成員給移除了,改用了以下兩名新成員
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
此處需更改兩個地方 
a. 更改 file_operations 的 ioctl
struct file_operations scull_sngl_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
//.ioctl = scull_ioctl,
.unlocked_ioctl = scull_ioctl,
.open = scull_s_open,
.release = scull_s_release,
};
b. 更改 scull_ioctl 的函數原型 (main.c scull.h)
  • //int scull_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
  • long scull_ioctl( struct file *filp, unsigned int cmd, unsigned long arg)

4. 隱含宣告函式 「init_MUTEX」 [-Werror=implicit-function-declaration]

在新版本的linux内核中,已經廢除init_mutex,新版本直接使用sema_init()。原始的定義如下 (linux 2.6.xx 時仍存在此定義)
#define init_MUTEX(sem) sema_init(sem, 1)
#define init_MUTEX_LOCKED(sem) sema_init(sem, 0)
因此可更改如下:
//init_MUTEX(&scull_devices[i].sem);
sema_init(&scull_devices[i].sem, 1);

5. 錯誤: 「TASK_INTERRUPTIBLE」 undeclared (first use in this function)
此常數定義在 sched.h
需在 access.c 與 pipe.c 加上 #include <linux/sched.h>  即可

6. 找不到 SPIN_LOCK_UNLOCKED’
原因:SPIN_LOCK_UNLOCKED has been deprecated since 2.6.19 and will get removed in 2.6.39。
改法:
// static spinlock_t scull_u_lock = SPIN_LOCK_UNLOCKED;
static DEFINE_SPINLOCK(scull_u_lock);

7. 錯誤: 「struct task_struct」 沒具名為 「uid」 的成員
原因:struct task_struct 已經重新定義
改法:
current->uid 改成 current->cred->uid
current->euid 改成 current->cred->euid
current->comm 改成 current->cred->comm
在 kernel 3.13.11 之後版本需修改如下:
current->uid 改成 current->cred->uid.val
current->euid 改成 current->cred->euid.val

參考資料:
http://stackoverflow.com/questions/30143654/android-kernel-compile-error-incompatible-types-when-assigning-to-type-uid-t