我在内核空间编写了SPI字符设备驱动程序。我现在可以通过用户空间中的以下功能进行通信。
1.open("/dev/rfk_spi", O_RDWR);
2.write(fd,buf,sizeof(buf)/sizeof(buf[0]));
3.read(fd,tab,sizeof(tab)/sizeof(tab[0]));
但是,我想实现一些具有一些参数和返回类型的函数。 我想从用户空间program.Suppose
访问此功能 1.unsigned char function1(unsigned int,unsigned char*);
2.void function2(struct student record);
然后如何在内核空间/用户空间中编写代码来交换数据。
这些是我的核心功能:
1.static int spi_open(struct inode *inode,struct file *filp) {}
2.static int spi_release(struct inode *inode,struct file *filp){}
3.static ssize_t spi_read(struct file *filp,char __user *buf,size_t count,loff_t *f_ops){}
4.static ssize_t spi_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_ops){}
static const struct file_operations spi_fops =
{
.owner=THIS_MODULE,
.open=spi_open,
.read=spi_read,
.release=spi_release,
.write=spi_write,
};
static struct miscdevice misc =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &spi_fops,
};
6.static int __init spi_init(void){}
7.static void __exit spi_exit(void){}
module_init(spi_init);
module_exit(spi_exit);
MODULE_LICENSE("GPL");
请指导我解决我的问题!
更新 - 在处理@jjm的建议时,现在收到以下回复:
我已经交叉编译了chardev.c,chardev.h和make chardev.ko
root@rfk-desktop:# ls
chardev.c chardev.h chardev.ko chardev.mod.c chardev.mod.o chardev.o ioctl ioctl.c Makefile modules.order Module.symvers
root@rfk-desktop:# file chardev.ko
chardev.ko: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), not stripped
root@rfk-desktop:# file ioctl
ioctl: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, stripped
我将文件复制到开发板并注册
[root@FriendlyARM 2.6.32.2-FriendlyARM]# modprob chardev
[root@FriendlyARM 2.6.32.2-FriendlyARM]# mknod char_dev c 100 0
但是当我运行测试程序时:)
[root@FriendlyARM /mnt]# ./ioctl
Can't open device file: char_dev
请回复我失踪的地方?
UPDATE - 一切正常,没问题!!!&我将很快发布更新的源代码及详细说明!!
拜托,任何人都可以告诉我为什么我会得到-Ve标记!!有没有错误的信息?还是缺了?其他什么?
答案 0 :(得分:1)
您可以将IOCTL用于此目的。您也可以将ioctl函数注册到您的文件操作。例如
static const struct file_operations spi_fops =
{
.owner=THIS_MODULE,
.open=spi_open,
.read=spi_read,
.release=spi_release,
.write=spi_write,
.unlocked_ioctl=spi_ioctl
};
然后你可以使用
copy_from_user
用于从用户空间和
接收参数的函数copy_to_user
将参数传递给用户空间的函数。在IOCTL中使用这些函数来实现读写以外的功能。
答案 1 :(得分:0)
我会反对在Stackoverflow上的流行投票,并建议使用sysfs有几个原因:
答案 2 :(得分:0)
我的源代码正常工作请看看。如果任何人受益或看到对他人有帮助,请给出一些+ Ve标记。
另外请告诉我为什么我会得到这个问题的标记!!
1" chardev.c"
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include "./chardev.h"
#define SUCCESS 0
#define DEVICE_NAME "char_dev_rfk"
#define BUF_LEN 80
static int Device_Open = 0;
static char Message[BUF_LEN];
static char *Message_Ptr;
static int device_open(struct inode *inode, struct file *file)
{
printk(KERN_INFO "\n\rdevice_open(%p)\n", file);
if (Device_Open) return -EBUSY;
Device_Open++;
Message_Ptr = Message;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static int device_release(struct inode *inode, struct file *file)
{
printk(KERN_INFO "\n\rdevice_release(%p,%p)\n", inode, file);
Device_Open--;
module_put(THIS_MODULE);
return SUCCESS;
}
static ssize_t device_read(struct file *file,char __user * buffer,size_t length, loff_t * offset)
{
int bytes_read = 0;
printk(KERN_INFO "\n\rdevice_read(%p,%p,%d)\n", file, buffer, length);
if (*Message_Ptr == 0) return 0;
while (length && *Message_Ptr_k)
{
put_user(*(Message_Ptr_k++), buffer++);
length--;
bytes_read++;
}
printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);
return bytes_read;
}
static ssize_t device_write(struct file *file,const char __user * buffer, size_t length, loff_t * offset)
{
int i;
printk(KERN_INFO "\n\rdevice_write(%p,%s,%d)", file, buffer, length);
for (i = 0; i < length && i < BUF_LEN; i++)
get_user(Message[i], buffer + i);
Message_Ptr = Message;
return i;
}
int device_ioctl(struct inode *inode, struct file *file, unsigned int ioctl_num, unsigned long ioctl_param)
{
int i;
char *temp;
char ch;
switch (ioctl_num)
{
case IOCTL_SET_MSG:
temp = (char *)ioctl_param;
get_user(ch, temp);
for (i = 0; ch && i < BUF_LEN; i++, temp++)
get_user(ch, temp);
device_write(file, (char *)ioctl_param, i, 0);
break;
case IOCTL_GET_MSG:
i = device_read(file, (char *)ioctl_param, 99, 0);
put_user('\0', (char *)ioctl_param + i);
break;
case IOCTL_GET_NTH_BYTE:
return Message[ioctl_param];
break;
}
return SUCCESS;
}
struct file_operations Fops =
{
.read = device_read,
.write = device_write,
.ioctl = device_ioctl,
.open = device_open,
.release = device_release,
};
int init_module()
{
int ret_val;
ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
if (ret_val < 0)
{
printk(KERN_ALERT "%s failed with %d\n","Sorry, registering the character device ", ret_val);
return ret_val;
}
printk(KERN_INFO "%s The major device number is %d.\n","Registeration is a success", MAJOR_NUM);
return 0;
}
void cleanup_module()
{
}
MODULE_LICENSE("GPL");
2&#34; chardev.h&#34;
#ifndef CHARDEV_H
#define CHARDEV_H
#include <linux/ioctl.h>
#define MAJOR_NUM 100
#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)
#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)
#define DEVICE_FILE_NAME "char_dev_rfk"
#endif
3&#34; ioctl.c&#34;
#include "chardev.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
ioctl_set_msg(int file_desc, char *message)
{
int ret_val;
printf("\n\rioctl_set_msg():Called\n");
ret_val = ioctl(file_desc, IOCTL_SET_MSG, message);
if (ret_val < 0)
{
printf("ioctl_set_msg failed:%d\n", ret_val);
exit(-1);
}
}
ioctl_get_msg(int file_desc)
{
int ret_val;
char message[100];
printf("\n\rioctl_get_msg():Called\n");
ret_val = ioctl(file_desc, IOCTL_GET_MSG, message);
if (ret_val < 0)
{
printf("ioctl_get_msg failed:%d\n", ret_val);
exit(-1);
}
printf("\n\rget_msg message:%s\n", message);
}
ioctl_get_nth_byte(int file_desc)
{
int i;
char c;
printf("\n\rioctl_get_nth_byte():Called\n");
printf("\n\rget_nth_byte message:");
i = 0;
do {
c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++);
if (c < 0)
{
printf("ioctl_get_nth_byte failed at the %d'th byte:\n",i);
exit(-1);
}
putchar(c);
} while (c != 0);
putchar('\n');
}
main()
{
int file_desc, ret_val;
char *msg = "Message passed from Uesr:Rofique\n";
file_desc = open("./char_dev_rfk", O_RDWR);
if (file_desc < 0)
{
printf("Can't open device file: %s\n", DEVICE_FILE_NAME);
exit(-1);
}
ioctl_set_msg(file_desc, msg);
ioctl_get_msg(file_desc);
close(file_desc);
}
我已经为ARM9板交叉编译了它。所以,按如下方式制作文件。
4&#34;生成文件&#34;
ifneq ($(KERNELRELEASE),)
obj-m:= chardev.o
else
CROSS=arm-linux-
KDIR := /opt/linux-2.6.32.2/
all:ioctl
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
ioctl:ioctl.c
$(CROSS)gcc -o ioctl ioctl.c
$(CROSS)strip ioctl
clean:
rm -f *.ko *.o *.mod.o *.mod.c *symvers modul* ioctl
endif