简介
用户空间与内核空间的交互方式如下,下面逐一详细说明。
procfs
netlink
文件io读写
ioctl
debugfs
sysfs
procfs:在Linux系统中,procfs是一种伪文件系统,它提供了一种以文件的形式访问内核数据结构和系统信息的接口。用户空间可以通过读取和写入/proc目录下的文件来与内核进行交互。
netlink:Netlink是Linux内核中一种用于进程间通信的机制,它允许用户空间的进程与内核空间的进程进行双向通信。用户空间的进程可以通过创建和使用Netlink套接字的方式,与内核空间的进程进行交互。
文件IO读写:用户空间的进程可以通过标准的文件IO操作(如open、read、write等)与内核空间进行交互。这种方式往往用于与设备驱动程序进行通信,通过读写设备文件来访问设备。
ioctl:ioctl(Input/Output Control)是Linux中的一个系统调用,它可以用于在用户空间和内核空间之间进行特殊操作的交互。特定的指令可以通过ioctl传递给设备驱动程序,实现特定的功能。
debugfs:debugfs是Linux内核中的一个文件系统,用于调试目的。用户空间的进程可以通过读写debugfs文件系统中的文件来获取和修改内核的调试信息,从而与内核进行交互。
sysfs:sysfs是Linux内核中的一个文件系统,用于提供设备和驱动程序的信息。用户空间的进程可以通过读取sysfs文件系统中的文件来获取设备和驱动程序的相关信息,也可以通过写入sysfs文件系统中的文件来配置相关参数,与内核进行交互。
procfs是内核的进程文件系统,被挂载到 /proc目录下,通过内核访问进程信息。
我们可以创建proc文件和内核交互。
/proc/sys目录下存放了一些内核变量,文件和目录都是以ctl_table结构定义的。
ctl_table结构的注册、注销是通过kernel/sysctl.c中定义的register_sysctl_table和unregister_sysctl_table实现的。
procfs初始化首先看下fs/proc/ 文件夹里的Makefile。这里参考fs/proc/root.c。
void __init proc_root_init(void)
{
struct vfsmount *mnt;
int err;
proc_init_inodecache();
err = register_filesystem(&proc_fs_type);
if (err)
return;
mnt = kern_mount_data(&proc_fs_type, &init_pid_ns);
if (IS_ERR(mnt)) {
unregister_filesystem(&proc_fs_type);
return;
}
init_pid_ns.proc_mnt = mnt;
proc_symlink("mounts", NULL, "self/mounts");
proc_net_init();
#ifdef CONFIG_SYSVIPC
proc_mkdir("sysvipc", NULL);
#endif
proc_mkdir("fs", NULL);
proc_mkdir("driver", NULL);
proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */
#if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
/* just give it a mountpoint */
proc_mkdir("openprom", NULL);
#endif
proc_tty_init();
#ifdef CONFIG_PROC_DEVICETREE
proc_device_tree_init();
#endif
proc_mkdir("bus", NULL);
proc_sys_init();
}
proc目录下创建目录
struct proc_dir_entry *proc_mkdir(const char *name,
struct proc_dir_entry *parent)
{
return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
}
struct proc_dir_entry *entry = create_proc_entry("my_proc", 0, NULL);
if(entry)
{
entry->read_proc = XXX_proc_read;
entry->write_proc = XXX_proc_write;
}
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
struct proc_dir_entry *parent)
{
struct proc_dir_entry *ent;
nlink_t nlink;
if (S_ISDIR(mode)) {
if ((mode & S_IALLUGO) == 0)
mode |= S_IRUGO | S_IXUGO;
nlink = 2;
} else {
if ((mode & S_IFMT) == 0)
mode |= S_IFREG;
if ((mode & S_IALLUGO) == 0)
mode |= S_IRUGO;
nlink = 1;
}
ent = __proc_create(&parent, name, mode, nlink);
if (ent) {
if (proc_register(parent, ent) < 0) {
kfree(ent);
ent = NULL;
}
}
return ent;
}
extern struct proc_dir_entry *proc_net_fops_create
(struct net *net, const char *name, mode_t mode, const struct file_operations *fops);
extern void proc_net_remove(struct net *net, const char *name);
extern struct proc_dir_entry *proc_net_mkdir
(struct net *net, const char *name, struct proc_dir_entry *parent);
在文件系统中位网络命名空间创建一个proc入口。
static int __net_init netlink_net_init(struct net *net)
{
#ifdef CONFIG_PROC_FS
if (!proc_net_fops_create(net, "netlink", 0, &netlink_seq_fops))
return -ENOMEM;
#endif
return 0;
}static const struct file_operations netlink_seq_fops = {
.owner = THIS_MODULE,
.open = netlink_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release_net,
};
static const struct seq_operations netlink_seq_ops = {
.start = netlink_seq_start,
.next = netlink_seq_next,
.stop = netlink_seq_stop,
.show = netlink_seq_show,
};
static int netlink_seq_open(struct inode *inode, struct file *file)
{
return seq_open_net(inode, file, &netlink_seq_ops,
sizeof(struct nl_seq_iter));
}
内容待补充
内容待补充
内容待补充
内容待补充