1. 程式人生 > >Linux裝置驅動程式安裝fatal error: linux/module.h: No such file or directory

Linux裝置驅動程式安裝fatal error: linux/module.h: No such file or directory

在做Linux裝置驅動程式安裝實驗時,執行gcc -c mydev.c產生fatal error: linux/module.h: No such file or directory錯誤資訊

mydev.c程式碼如下:

#ifndef __KERNEL__
#define __KERNEL__
#endif

#ifndef MODULE
#define MODULE
#endif

#define __NO_VERSION__

#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/version.h>
#include<linux/config.h>

#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include<linux/modversions.h>
#endif

#include<linux/fs.h>
#include<linux/wrapper.h>
#include<linux/types.h>
#include<asm/segment.h>

#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a,b,c) ((a)*65535+(b)*256+(c))
#endif

/*Conditional compilation. LINUX_VERSION_CODE is
* the code (as per KERNEL_VERSION) of this version.
*/
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)
#include <asm/uaccess.h>	/*for put_user*/
#endif

#define SUCCESS 0
#define DEVICE_NAME "kueng_char_dev"
#define BUF_LEN 50

static int Device_Open = 0;
static char Message[BUF_LEN];
static int Major;

static int mydev_open(struct inode * inode, struct file * file)
{
	if (Device_Open)		/*被佔用則開啟失敗*/
		return -EBUSY;
	Device_Open = 1;
	MOD_INC_USE_COUNT;		/*模組使用者數加1,非0不能解除安裝*/
	return 0;
}

static int mydev_release(struct inode * inode, struct file * file)
{
	Device_Open = 0;		/*釋放模組*/
	MOD_DEC_USE_COUNT;		/*模組使用者數減1*/
	return 0;
}

static ssize_t mydev_read(struct file * file, char * buffer, size_t length, loff_t * f_pos)
{
	int bytes_read = 0;
	/*確認訪問使用者記憶體空間合法性*/
	if (verify_area(VERIFY_WRITE, buffer, length) == -EFAULT)
		return -EFAULT;
	/*由系統空間到使用者空間複製*/
	bytes_read = copy_to_user(buffer, Message, length);
	return bytes_read;
}

static ssize_t mydev_write(struct file * file, const char * buffer, size_t length, loff_t *f_pos)
{
	int len = BUF_LEN < length ? BUF_LEN : length;
	/*確認訪問使用者記憶體空間合法性*/
	if (verify_area(NERIFU_READ, buffer, length) == -EFAULT)
		return -RFAULT;
	/*由使用者空間到記憶體空間複製*/
	copy_from_user(Message, buffer, len);
	return length;
}

/*裝置驅動程式的入口點*/
struct file_operations Fops =
{
	release:device_release,
	open : device_open,
	read : device_read,
	write : device_write
};

int init_module(void)
{
	/*設備註冊*/
	Major = register_chrdev(0, DEVICE_NAME, &Fops);
	if (Major < 0)
	{
		printk("Registering character device failed with %d\n", Major);
		return Major;
	}
	printk("Registration success with Major device number %d \n", Major);
	return 0;
}

void cleanup_module(void)
{
	int ret;
	/*設備註銷*/
	ret = unregister_chrdev(Major, DEVICE_NAME);
	if (ret < 0)
		printk("Error in unregister_chrdev: %d\n", ret);
	return 0;
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("KUENG");


錯誤原因:需要呼叫核心程式碼的標頭檔案,這些檔案在/usr/src目錄下,一般以“linux”開頭,在實驗之前要對這些檔案是否已經安裝,以及核心程式碼與當前系統核心版本是否一致進行確認。 用-I指定核心標頭檔案目錄後 錯誤變為fatal error: asm/linkage.h: No such file or directory 發現並沒有asm這個資料夾,只有asm-generic資料夾 查閱資料後的解決辦法:(參考:http://www.cnblogs.com/QuLory/archive/2012/10/23/2736339.html) 使用kbuild進行模組編譯:

核心思想是,通過-C指明系統上的核心體系路徑,通過M=指明模組原始檔路徑,然後自己構造一個makefile檔案,從而實現編譯過程。

Makefile obj-m := mydev.o all :
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 記得make前面是Tab符 編譯後發現MOD_INC_USE_COUNTMOD_DNC_USE_COUNT未宣告,查閱資料後發現MOD_INC_USE_COUNTMOD_DNC_USE_COUNT2.5.x以後版本被移除,因此需要在redhat9.0環境下編譯。
執行gcc -c -O mydev.c -I /usr/src/linux-2.4-20-8/include後編譯成功 附test.c:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>

main(){
	int testdev;
	int i;
	char buf[50]="write to buf";
	printf("program test is running! \n");
	testdev=open("/dev/mydev",O_RDWR);
	if(testdev==-1)
	{
		printf("can not open file \n");
		exit(0);
	}
	write(testdev,buf,50);
	printf("write \"%s\" \n",buf);
	strcpy(buf,"changed buf");
	printf("buffer is changed to \"%s\" " ,buf);
	read(testdev,buf,50);
	printf("read from dev is \"%s\"\n",buf);
	close(testdev);
}