linux3.10 proc文件系统实现原理

14 篇文章 11 订阅
订阅专栏

1 主要数据结构

我们列举某个proc目录,其与虚拟文件系统的数据结构关系如下:

文件或者目录打开的时候会为虚拟文件系统创建inode,对于proc文件系统,inode结构包含于结构体proc_inode,用于连接vfs:

struct proc_inode {
	struct pid *pid;
	int fd;
	union proc_op op;
	struct proc_dir_entry *pde; //指向该目录/文件对应的proc_dir_entry
	struct ctl_table_header *sysctl;
	struct ctl_table *sysctl_entry;
	struct proc_ns ns;
	struct inode vfs_inode;//Vfs的inode,用宏PROC_I(inode)可以通过inode得到对应的proc_inode
};

 每一个文件或者目录创建的时候都会构建一个结构体proc_dir_entry用于管理这个文件或者目录,与proc_inode不同的是,proc_dir_entry在文件或者目录创建的时候就会产生,但是proc_inode只有在打开的时候才会产生:

struct proc_dir_entry {
	unsigned int low_ino;
	umode_t mode;  //文件类型:包含S_IFDIR(目录) 或者S_IFREG(普通文件)等等
	nlink_t nlink;
	kuid_t uid;
	kgid_t gid;
	loff_t size;
	const struct inode_operations *proc_iops; //文件或者目录打开的时候会赋给vfs_inode->i_op
	const struct file_operations *proc_fops;//如果是目录在打开的时候付给vfs_inode->i_fop,如果是普通文件会赋值为proc_reg_file_ops
	struct proc_dir_entry *next, *parent, *subdir;
	void *data;
	atomic_t count;		/* use count */
	atomic_t in_use;	/* number of callers into module in progress; */
			/* negative -> it's going away RSN */
	struct completion *pde_unload_completion;
	struct list_head pde_openers;	/* who did ->open, but not ->release */
	spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
	u8 namelen;
	char name[];//存放目录项名
};

2 文件系统挂载

proc文件系统挂载会调用proc_mount函数:

static struct file_system_type proc_fs_type = {
	.name		= "proc",
	.mount		= proc_mount,
	.kill_sb	= proc_kill_sb,
	.fs_flags	= FS_USERNS_MOUNT,
};
static struct dentry *proc_mount(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data)
{
	int err;
	struct super_block *sb;
	struct pid_namespace *ns;
	char *options;
	if (flags & MS_KERNMOUNT) {
		ns = (struct pid_namespace *)data;
		options = NULL;
	} else {
		ns = task_active_pid_ns(current);
		options = data;

		if (!current_user_ns()->may_mount_proc)
			return ERR_PTR(-EPERM);
	}
    //分配并设置proc 文件系统的super_block
	sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns);
	if (IS_ERR(sb))
		return ERR_CAST(sb);

	if (!proc_parse_options(options, ns)) {
		deactivate_locked_super(sb);
		return ERR_PTR(-EINVAL);
	}

	if (!sb->s_root) {
		err = proc_fill_super(sb);//在该函数中分配dentry和inode结构
		if (err) {
			deactivate_locked_super(sb);
			return ERR_PTR(err);
		}

		sb->s_flags |= MS_ACTIVE;
	}

	return dget(sb->s_root);
}

看一下proc_fill_super的实现:

int proc_fill_super(struct super_block *s)
{
	struct inode *root_inode;

	s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;
	s->s_blocksize = 1024;
	s->s_blocksize_bits = 10;
	s->s_magic = PROC_SUPER_MAGIC;
	s->s_op = &proc_sops; //设置super_block的操作函数,后面分配inode的时候,会调用里面的proc_alloc_inode
	s->s_time_gran = 1;
	
	pde_get(&proc_root);
	root_inode = proc_get_inode(s, &proc_root);//分配inode
	if (!root_inode) {
		pr_err("proc_fill_super: get root inode failed\n");
		return -ENOMEM;
	}

	s->s_root = d_make_root(root_inode);//建立文件系统根目录的dentry
	if (!s->s_root) {
		pr_err("proc_fill_super: allocate dentry failed\n");
		return -ENOMEM;
	}

	return proc_setup_self(s);//这个在根目录下创建了名字叫self的dentry和inode节点,具体用途不知。。
}

在proc_get_inode函数中分配了inode

struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
{
	struct inode *inode = new_inode_pseudo(sb);//调用super_block的alloc_inode函数,为其分配一个proc_inode结构,其中包含inode

	if (inode) {
		inode->i_ino = de->low_ino;
		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
		PROC_I(inode)->pde = de; //把proc_dir_entry结构赋值给proc_inode->pde,对于根目录,该结构是静态的proc_root

		if (de->mode) {
			inode->i_mode = de->mode;
			inode->i_uid = de->uid;
			inode->i_gid = de->gid;
		}
		if (de->size)
			inode->i_size = de->size;
		if (de->nlink)
			set_nlink(inode, de->nlink);
		WARN_ON(!de->proc_iops);
		inode->i_op = de->proc_iops;//proc的操作函数,具体节点的操作函数就是他
		if (de->proc_fops) {
			if (S_ISREG(inode->i_mode)) {
#ifdef CONFIG_COMPAT
				if (!de->proc_fops->compat_ioctl)
					inode->i_fop =
						&proc_reg_file_ops_no_compat;
				else
#endif
					inode->i_fop = &proc_reg_file_ops;//该操作函数在文件打开的时候会赋值给file结构体,如果是普通文件
			} else {
				inode->i_fop = de->proc_fops; //如果是目录,
			}
		}
	} else
	       pde_put(de);
	return inode;
}
struct proc_dir_entry proc_root = {
	.low_ino	= PROC_ROOT_INO, 
	.namelen	= 5, 
	.mode		= S_IFDIR | S_IRUGO | S_IXUGO, 
	.nlink		= 2, 
	.count		= ATOMIC_INIT(1),
	.proc_iops	= &proc_root_inode_operations, 
	.proc_fops	= &proc_root_operations,
	.parent		= &proc_root,
	.name		= "/proc",
};

上面的new_inode_pseudo函数会调用super_block的proc_alloc_inode,看一下该函数:

static struct inode *proc_alloc_inode(struct super_block *sb)
{
	struct proc_inode *ei;
	struct inode *inode;

	ei = (struct proc_inode *)kmem_cache_alloc(proc_inode_cachep, GFP_KERNEL);
	if (!ei)
		return NULL;
	ei->pid = NULL;
	ei->fd = 0;
	ei->op.proc_get_link = NULL;
	ei->pde = NULL;
	ei->sysctl = NULL;
	ei->sysctl_entry = NULL;
	ei->ns.ns = NULL;
	ei->ns.ns_ops = NULL;
	inode = &ei->vfs_inode;
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
	return inode;
}

可以看到,通过该函数分配proc_inode,并且返回其内部的inode结构,通过上面的函数,可以看到为文件系统的根目录创建了dentry,proc_inode,并且和proc_root关联起来。

3 proc文件注册

下面内容原文地址为:https://blog.csdn.net/chenying126/article/details/78069910

3.1创建目录/文件

proc_create用于创建proc文件;proc_mkdir用于创建proc目录。接口__proc_create用于完成目录/文件创建的主要工作。

3.2目录创建

void __init proc_root_init(void)
{
	……
    proc_mkdir("fs", NULL);
   	……
}
 
struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
        struct proc_dir_entry *parent, void *data)
{
    struct proc_dir_entry *ent;
 
    if (mode == 0)
        mode = S_IRUGO | S_IXUGO;
    
   // 目录或者文件都是由结构体proc_dir_entry 来描述,S_IFDIR表示创建的是目录
    ent = __proc_create(&parent, name, S_IFDIR | mode, 2); 
    if (ent) {
        ent->data = data;
        ent->proc_fops = &proc_dir_operations; // file_operations打开的时候会赋给inode
        ent->proc_iops = &proc_dir_inode_operations; // inode_operations打开的时候会赋给inode
        parent->nlink++;
//建立层次关系,proc_dir_entry->parent指向父目录,proc_dir_entry->subdir_node插入到parent->subdir中
        if (proc_register(parent, ent) < 0) { 
            kfree(ent);
            parent->nlink--;
            ent = NULL;
        }
    }
    return ent;
}

对于目录来说proc_dir_operations都是空实现

static const struct file_operations proc_dir_operations = {
    .llseek         = generic_file_llseek,
    .read           = generic_read_dir,
    .iterate_shared     = proc_readdir,
};

proc_dir_inode_operations会在open的时候赋给inode,后续会重点讲解函数proc_lookup

static const struct inode_operations proc_dir_inode_operations = {
    .lookup     = proc_lookup,
    .getattr    = proc_getattr,
    .setattr    = proc_notify_change,
};

3.3文件创建

如果在/proc目录下创建一个proc文件,具体应该怎么做,先申明一个file_operations,结构,然后注册:

static const struct file_operations version_proc_fops = {
    .open       = version_proc_open,
    .read       = seq_read,
    .llseek     = seq_lseek, 
    .release    = single_release, 
};                         
 
static int __init proc_version_init(void)
{
    proc_create("version", 0, NULL, &version_proc_fops);
    return 0;
}

上面函数最终会调用到proc_create_data,传递下来的参数&version_proc_fops对应到下面的proc_fops

struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
                    struct proc_dir_entry *parent,
                    const struct file_operations *proc_fops,
                    void *data)
{
    struct proc_dir_entry *pde;
    if ((mode & S_IFMT) == 0)
        mode |= S_IFREG; //表示创建的是普通文件,
        
	……
    pde = __proc_create(&parent, name, mode, 1); //分配文件对应的proc_dir_entry并初始化,这边
//需要注意,传入的parent参数,如果传进去的parent为null,则会寻找根节点,把parent置为根节点
    if (!pde)   
        goto out;
    pde->proc_fops = proc_fops; //也就是version_proc_fops,文件打开的时候会赋给inode
    pde->data = data; 
    pde->proc_iops = &proc_file_inode_operations; //对于普通文件来说很多接口都没有实现
    if (proc_register(parent, pde) < 0) //建立文件在proc中的层次关系
        goto out_free;
    return pde;
	……
static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
{
	struct proc_dir_entry *tmp;
	int ret;
	
	ret = proc_alloc_inum(&dp->low_ino);
	if (ret)
		return ret;

	if (S_ISDIR(dp->mode)) {
		dp->proc_fops = &proc_dir_operations;
		dp->proc_iops = &proc_dir_inode_operations;
		dir->nlink++;
	} else if (S_ISLNK(dp->mode)) {
		dp->proc_iops = &proc_link_inode_operations;
	} else if (S_ISREG(dp->mode)) {
		BUG_ON(dp->proc_fops == NULL);
		dp->proc_iops = &proc_file_inode_operations;
	} else {
		WARN_ON(1);
		return -EINVAL;
	}

	spin_lock(&proc_subdir_lock);

	for (tmp = dir->subdir; tmp; tmp = tmp->next)
		if (strcmp(tmp->name, dp->name) == 0) {
			WARN(1, "proc_dir_entry '%s/%s' already registered\n",
				dir->name, dp->name);
			break;
		}

	dp->next = dir->subdir;
	dp->parent = dir;
	dir->subdir = dp;//和父目录的proc_dir_entry关联起来
	spin_unlock(&proc_subdir_lock);

	return 0;
}

从上面的源码分析也可以看到,创建proc文件或者目录的时候,只创建了该节点的proc_dir_entry结构,并把该结构和上层目录相关联,dentry和inode只有在打开该文件的时候才会被创建。

4 proc读写原理

以上面新建的/proc/version文件为例,看一下具体是怎么读写该文件的。

proc文件夹一般来说,都存在于上级文件系统化中,但是proc文件系统挂载在该文件夹下面,所以在open version文件,往下搜索的时候,先搜索proc节点,最终会找到proc文件系统根节点‘/’的dentry和inode结构,这两个结构在上面一节文件系统挂载的时候可以看到,已经被创建。接着就再往下搜索,为version文件创建dentry和inode节点。具体的函数调用流程看下图:

4.1文件打开

文件搜索的源码分析,在之前的sysfs文件系统博文中已经讲过,这边不再分析了,主要分析几个重点函数。继续之前的例子,当搜索到version文件时,需要为其建立inode和dentry,上层目录就是proc文件系统的根目录。所以我们调用根目录的inode的lookup方法,上面文件系统挂载的时候可以看到inode->i_op = de->proc_iops;de是定义的静态的proc_root;对应的是proc_root_inode_operations操作集函数,具体lookup函数为proc_root_lookup:

proc_root_lookup

     -------------->proc_lookup

            --------------->proc_lookup_de

struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
		struct dentry *dentry)
{
	struct inode *inode;

	spin_lock(&proc_subdir_lock);
	for (de = de->subdir; de ; de = de->next) { //找父proc_dir_entry对应的子proc_dir_entry,主要根据文件名来比对
		if (de->namelen != dentry->d_name.len)
			continue;
		if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
			pde_get(de);
			spin_unlock(&proc_subdir_lock);
			inode = proc_get_inode(dir->i_sb, de);//找到子proc_dir_entry,为其分配inode结构,关联proc_inode和proc_dir_entry
			if (!inode)
				return ERR_PTR(-ENOMEM);
			d_set_d_op(dentry, &proc_dentry_operations);//为当前节点的dentry设置dentry_operations函数
			d_add(dentry, inode);//dentry->d_inode = inode;把dentry和indoe关联起来。
			return NULL;
		}
	}
	spin_unlock(&proc_subdir_lock);
	return ERR_PTR(-ENOENT);
}

 经过上面的函数,dentry,inode,proc_inode都有了,再看do_dentry_open后面的流程。

文件的file->f_op来源于inode->i_fop,而i_fop在之前初始化为proc_reg_file_ops:

static const struct file_operations proc_reg_file_ops = {
	.llseek		= proc_reg_llseek,
	.read		= proc_reg_read,
	.write		= proc_reg_write,
	.poll		= proc_reg_poll,
	.unlocked_ioctl	= proc_reg_unlocked_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl	= proc_reg_compat_ioctl,
#endif
	.mmap		= proc_reg_mmap,
	.open		= proc_reg_open,
	.release	= proc_reg_release,
};

proc_reg_open会调用到proc_dir_entry->proc_fops->open,proc_dir_entry就是version文件注册的proc结构,前面注册的时候已经看到,其proc_fops就是前面的version_proc_fops :

static int version_proc_open(struct inode *inode, struct file *file)
{
    return single_open(file, version_proc_show, NULL);
}
 
int single_open(struct file *file, int (*show)(struct seq_file *, void *),
        void *data)
{
    struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL);
    int res = -ENOMEM;
    
    if (op) {   
        op->start = single_start;
        op->next = single_next;
        op->stop = single_stop;
        op->show = show;  //也就是前面提到的version_proc_show
        res = seq_open(file, op);
		……
    return res;
}
 
int seq_open(struct file *file, const struct seq_operations *op)
{       
    struct seq_file *p;    
    p = kzalloc(sizeof(*p), GFP_KERNEL);
 
    file->private_data = p;  //与vfs中的file连接
        
    p->op = op; //设置顺序文件系统的seq_operations
    p->file = file;
    
    file->f_version = 0;
 
    file->f_mode &= ~FMODE_PWRITE;
    return 0;
}

4.2文件读取

 函数proc_reg_read是vfs read进入proc的入口。


static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{   
    ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
    struct proc_dir_entry *pde = PDE(file_inode(file));
    ssize_t rv = -EIO;
    if (use_pde(pde)) {
        read = pde->proc_fops->read;  //调用version文件注册的proc读函数
        if (read)
            rv = read(file, buf, count, ppos);
        unuse_pde(pde);
    }
    return rv;
}

pde->proc_fops->read函数就是seq_read函数:

ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
    struct seq_file *m = file->private_data;
    size_t copied = 0;
    loff_t pos;
    size_t n;
    void *p;
    int err = 0;
 
    if (!m->buf) {//因为这是一个通用函数,它并不知道会读取多少数据所以这里暂且分配一页数据
        m->buf = seq_buf_alloc(m->size = PAGE_SIZE);
        if (!m->buf)
            goto Enomem;
    }
    /* if not empty - flush it first */
    if (m->count) {//如果buffer中有数据先将数据拷贝到用户空间
        n = min(m->count, size);
        err = copy_to_user(buf, m->buf + m->from, n);
        if (err)
            goto Efault;
        m->count -= n;
        m->from += n;
        size -= n;
        buf += n;
        copied += n;
        if (!m->count) {
            m->from = 0;
            m->index++;
        }
        if (!size)
            goto Done;
}
    /* we need at least one record in buffer */
    pos = m->index;
    p = m->op->start(m, &pos);
    while (1) {//测试先前分配的buffer够不够容纳将要读取的数据,如果不够就释放重新分配更大内存
        err = PTR_ERR(p);
        if (!p || IS_ERR(p))
            break;
        err = m->op->show(m, p); //尝试将数据拷贝到buffer中
        if (err < 0)
            break;
        if (unlikely(err))
            m->count = 0;
        if (unlikely(!m->count)) {
            p = m->op->next(m, p, &pos);
            m->index = pos;
            continue;
        }
        if (m->count < m->size) //如果m->count 等于 m->size就说明buffer满了,buffer不够用
            goto Fill;
        m->op->stop(m, p);
        kvfree(m->buf);//释放掉之前不够用的buffer
        m->count = 0;
        m->buf = seq_buf_alloc(m->size <<= 1);//分配更大内存
        if (!m->buf)
            goto Enomem;
        m->version = 0;
        pos = m->index;
        p = m->op->start(m, &pos);
    }
    m->op->stop(m, p);
    m->count = 0;
    goto Done;
Fill:
    /* they want more? let's try to get some more */
    while (m->count < size) {
        size_t offs = m->count;
        loff_t next = pos;
        p = m->op->next(m, p, &next);
        if (!p || IS_ERR(p)) {
            err = PTR_ERR(p);
            break;
        }
        err = m->op->show(m, p);//将剩余的数据拷贝到buffer
        if (seq_has_overflowed(m) || err) {
            m->count = offs;
            if (likely(err <= 0))
                break;
        }
        pos = next;
    }
    m->op->stop(m, p);
    n = min(m->count, size);
    err = copy_to_user(buf, m->buf, n);//将buffer中的数据拷贝到用户空间内存
    if (err)
        goto Efault;
    copied += n;
    m->count -= n;
    if (m->count)
        m->from = n;
    else
        pos++;
    m->index = pos;
Done:
    if (!copied)
        copied = err;
    else {
        *ppos += copied;
        m->read_pos += copied;
    }
    file->f_version = m->version;
    mutex_unlock(&m->lock);
    return copied;
}

 

Linux 操作系统原理 — 网卡驱动程序初始化流程
烟云的计算
03-16 1432
Init 系统的入口在 linux/init/main.c start_kernel(),是 Kernel 真正的初始化流程入口,start_kerenl() 将会调用一系列的初始化函数,包括:CPU 平台初始化,Memory 初始化,Interrupt 初始化,Process Scheduling 初始化,TCP/IP Stack 初始化等,目的是最终建立起基本完整的 Linux Kernel ENV。:在 /proc/net/ 目录下创建各类协议文件,注册相关的协议文件操作函数。
proc文件系统_每进程信息形成原理、目录遍历方式、位图查找
04-04 3339
我们知道在linux中,proc系统中对于每个进程都有一个进程相关的目录,里面描述了该进程各个方面详细的信息,本文探讨3个问题: 1: /proc目录下每进程子目录的形成[动态遍历当前进程列表形成] 2:每进程子目录下子目录/子文件的形成[静态数组] 3:/proc/net/子目录下子目录、子文件形成[系统初始化时形成] 内容:点击打开链接 0 首先介绍proc_dir_entry的层次
linux+proc+原理,Linux内核中的Proc文件系统(一)
weixin_29202687的博客
05-15 408
(1)/proc文件系统的特点和/proc文件的说明/proc文件系统是一种特殊的、由软件创建的文件系统,内核使用它向外界导出信息,/proc系统只存在内存当中,而不占用外存空间。/proc下面的每个文件都绑定于一个内核函数,用户读取文件时,该函数动态地生成文件的内容。也可以通过写/proc文件修改内核参数(2)/proc目录下的文件分析/proc/$pid关于进程$pid的信息目录。每个进程在/...
linux /proc 文件系统介绍
最新发布
toyijiu的专栏
07-19 374
proc文件系统提供了一种简单而强大的机制,允许用户空间程序和内核之间进行交互,实现了对内核参数的动态查看和修改,而无需重新编译内核或重启系统
独家:深度介绍Linux内核是如何工作的
weixin_33978016的博客
03-29 241
【Csdn 3月27日编译】本文发表于Linux Format magazine杂志,作者从技术深度上解释了Linux Kernel是如何工作的。相信对Linux开发者来说有不小的帮助。 牛津字典中对"kernel"一词的定义是:"较软的、通常是一个坚果可食用的部分。"当然还有第二种定义:"某个东西核心或者最重要的部分。"对Linux来说,它的Kernel无疑属于第二种解释。让我们来看看这个...
Linux在虚拟文件系统/proc中实现文件操作
hrdate(菜菜菜带带带)
11-20 2064
一、实验目的 1、理解Linux中虚拟文件系统的内容 2、学习编写内核模块的方法 3、在虚拟文件系统/proc中实现文件操作算法 二、实验环境 Centos7.9,vim 三、实验内容 编写一个内核模块,在/proc文件系统中增加一个目录hello,并在这个目录中增加一个文件world,文件的内容为hello world。 四、实验原理 实验中用到的系统调用函数 /proc 文件系统Linux上的一种虚拟文件系统,存储的是当前内核运行状态的一系列特殊文件,用户可以通过这些文件查看有关系统硬件及当前正在运行
proc】使用proc_create_data函数在proc下创建节点
诸葛一帆丶的博客
01-27 8773
前情提要: 移植代码的时候遇到create_proc_read_entry函数,新的内核里已经没有这个函数了,只能找对应的替换。 proc_create_data函数就是可以替换掉它,本文主要讲解下如何使用proc_create_data,以及相关的参数配置。 proc_create_data函数 函数定义在“linux/proc_fs.h”头文件中 extern struct proc_dir_entry *proc_create_data(const char *, umode_t,.
LINUX系统管理白皮书
09-18
5.1 proc文件系统的设置 36 5.2 二进制文件的安装 37 5.3 另一个例子 37 5.4 设置主机名 37 5.5 分配IP地址 37 5.6 编写主机和网络文件 39 5.7 IP接口配置 40 5.7.1 回送接口 40 5.7.2 以太网接口 41 5.7.3...
创建proc文件的三种方法
赵凯月的博客
08-24 1408
在做内核驱动开发的时候,可以使用/proc下的文件,获取相应的信息,以便调试。大多数/proc下的文件是只读的,但为了示例的完整性,都提供了写方法。方法一:使用 create_proc_entry 创建 proc 文件(简单,但写操作有缓冲区溢出的危险);方法二:使用 proc_create 和 seq_file 创建 proc 文件(较方法三简洁);方法三:使用 proc_create_data 和 seq_file 创建 proc 文件(较麻烦,但比较完整);
Zookeeper
qq_45335413的博客
10-01 268
1、解压:tar -zxvf zookeeper包名 解压到 /usr/local/zookeeper 2、设置环境变量 vi ~/.bash_profile (~/表示用户目录 ./ 当前目录 …/ 上级目录) ZOOKEEPER_HOME=/usr/local/zookeeper/zookeeper-3.4.10 export ZOOKEEPER_HOME PATH=$ZOOKEEPER_HOME/bin:$PATH export PATH #这一行不加可能会拒绝运行 export
内核proc文件系统与seq接口(2)---内核proc文件系统编程接口
weixin_39094034的博客
12-03 495
所有要使用 proc的内核模块都应当包含头文件。首先要了解以下proc编程中最重要的数据结构: struct proc_dir_entry { unsigned int low_ino; unsigned int namelen; const char *name; // 入口文件名 mode_t mode; // 文件访问权限模式 nlink_t nlink; uid_t uid; // 文件的用户ID gid_t gid; // 文件的组ID loff...
Linux内核编程(07):procfs文件系统
qq_29023095的博客
02-27 2648
零、课程计划 用户空间与内核空间的交互方式:文件I/O(read、write)、ioctl、procfs、debugfs、sysfs、netlink。 procfs简介:基于内存的文件系统,设计初期用于只是用于记录进程的相关信息,所以名称为procfs。 本期目标: 搞清楚proc下面文件的生成机制、工作机制 如何使用proc编程API接口去生成这些文件目录、删除目录、修改内容。 如何使用proc接口去调试内核模块或者驱动,通过proc直接修改寄存器。 一、procfs快速入门 ​ pro
通过proc文件系统输出必要的Linux内核信息(上)
tanglinux
02-05 4908
开发平台:Ubuntu 11.04     编译器:gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)     内核源码:linux-2.6.38.8.tar.bz2       proc是基于内存的文件系统,用来实现外界与Linux内核的信息交互(通过/proc目录下的各种文件)。     1、proc文件系统的初始化     proc
文件系统(十二)—伪文件系统
奇小葩
06-20 1636
前文中我们已经分析了文件系统,而文件系统的精髓所在是让用户可以通过文件描述符来对指定的进行一系列的操作。本章开始学习伪文件系统,伪文件系统和普通文件系统的区别在于,其对用户不可访问,即仅在内核态可见,从用户层的视角来看该文件系统并不存在。伪文件系统的作用是对一些操作系统中的元素进行封装,和普通的文件统一接口,如块设备,管道文件,套接字等。通过这种方式的统一封装,才实现了Linux一切皆文件的思想。如下图中红色的都应该算是伪文件系统,本章就学习其中的procfs/sysfs/pipefs。proc文件系统由p
Linuxproc文件系统
希希雾里
05-20 4490
proc文件系统-----在报告系统内核中的信息方面是非常好用的。
Linuxproc详解
zclinux的博客
07-12 5459
Linux系统上的/proc目录是一种文件系统,即proc文件系统。与其它常见的文件系统不同的是,/proc是一种伪文件系统(也即虚拟文件系统),存储的是当前内核运行状态的一系列特殊文件,用户可以通过这些文件查看有关系统硬件及当前正在运行进程的信息,甚至可以通过更改其中某些文件来改变内核的运行状态。基于/proc文件系统如上所述的特殊性,其内的文件也常被称作虚拟文件,并具有一些独特的特点。例如,其中有些文件虽然使用查看命令查看时会返回大量信息,但文件本身的大小却会显示为0字节。此外,这些特殊文件中大多数文件
深入解析Linux /proc文件系统
"这篇文章主要介绍了Linuxproc文件系统,它是一个虚拟文件系统,用于提供操作系统内部状态的实时信息。通过proc文件系统,用户可以获取CPU、内存、设备、中断等关键系统信息,以及进行系统配置。本文将探讨proc...
写文章

热门文章

  • Linux mtd与ubi关系详解,ubi使用命令总结 9105
  • arm 处理器进入和退出异常中断的过程 8599
  • HDR sensor 原理介绍 7411
  • 图像传感器的 DVP 信号 6966
  • linux poll的使用及其原理实现 6873

分类专栏

  • linux进程管理 14篇
  • 进程通信
  • 内存管理 9篇
  • linux中断处理 4篇
  • linux 3篇
  • camera接口 2篇
  • linux其他 2篇
  • h264 1篇
  • 图像处理 2篇
  • linux系统移植 8篇
  • uboot 4篇
  • 文件系统 14篇
  • 设备驱动 4篇
  • 进程同步 3篇
  • initramfs 1篇
  • smp
  • linux程序执行 2篇
  • 程序语言基础

最新评论

  • 常见的TSN网络协议之间的区别

    普通网友: 学到了!我也写了一篇获取【大厂面试真题解析、核心开发学习笔记、最新全套讲解视频、实战项目源码讲义、学习路线简历模板】的文章

  • linux v4l2-i2c 框架学习

    aiheshounai: 老哥源码能提供一下么?

  • 高通QNX基线编译原理

    CSDN-Ada助手: 推荐 Java 技能树:https://edu.csdn.net/skill/java?utm_source=AI_act_java

  • YUV颜色空间 —— 图像子采样

    m0_72045665: 你好,你前面又说常用的图像子采样格式有4:4:4,但是后面又说4:4:4并非子采样,而是普通的采样。所以到底是什么呢

  • 图像传感器的 DVP 信号

    lsn2002: 为什么粉色的波形中间有个缺口,是什么原因?

最新文章

  • 常见的TSN网络协议之间的区别
  • H264 编码原理
  • gdb调试core dump 文件
2024年4篇
2022年5篇
2021年5篇
2020年15篇
2019年80篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家玻璃钢雕塑玻璃钢中山市横栏玻璃钢雕塑公司玻璃钢花盆能暴晒吗商场外广场美陈河北艺术商场美陈费用镇江玻璃钢仿铜雕塑商家新会玻璃钢花盆花器常州花园玻璃钢花盆玻璃钢园林雕塑厂商商场风扇节美陈广西玻璃钢花盆厂天津多彩玻璃钢雕塑定制山西玻璃钢小品景观雕塑昭通市玻璃钢雕塑生产厂家河南景观玻璃钢雕塑销售厂家玻璃钢天猫雕塑工厂上海玻璃钢雕塑仿真牛灌云玻璃钢花盆惠阳玻璃钢花盆花器玻璃钢景观雕塑怎么做商场美陈灯光工厂商场美陈公司简介正宗玻璃钢雕塑哪家好佛山情景玻璃钢人物雕塑定西大型玻璃钢雕塑厂家白城园林景观玻璃钢雕塑工厂哪里有商场美陈装饰江西定制玻璃钢雕塑市场玻璃钢警钟雕塑厂家商丘玻璃钢人物雕塑香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化