用户空间和内核空间的通信

1.系统调用 2.命令行接口
3.共享内存 4.管道
5.信号 6.消息队列
7.套接字 8.文件系统

内核启动参数、 模块参数与 sysfs、sysctl、系统调用、netlink、procfs、seq_file、debugfs、relayfs,

模块参数与sysfs、procfs、debugfs、relayfs是基于文件系统的通信机制,用于内核空间向用户控件输出信息
sysctl、系统调用是由用户空间发起的通信机制
以上均为单工通信机制,在内核空间与用户空间的双向互动数据交换上略显不足
Netlink是基于socket的通信机制,由于socket本身的双共性、突发性、不阻塞特点,因此能够很好的满足内核与用户空间小量数据的及时交互

1、创建sysfs节点
典型的属性文件,利用sysfs_create_group 创建节点
static DEVICE_ATTR_RW(status);
static DEVICE_ATTR_RO(enabled);
用的是 kernfs_file_fops, 需要自己封装接口
这种方式一般是创建在已经存在的的sys文件系统下的 dev节点目录下
/*  add typec ccpin normalization node for  factory test start*/
typedef enum
{
    CC1,
    CC2,
    CCNone
} CCOrientation;

static int typec_polarity = CCNone;
static ssize_t ccpin_show(struct device *dev, struct device_attribute *attr,
                          char *buf)
{
    if (typec_polarity == CC1)
    return snprintf(buf, 256, "%s\n", "CC1");
    else if (typec_polarity == CC2)
    return snprintf(buf, 256, "%s\n", "CC2");
    else
        return snprintf(buf, 256, "%s\n", "Unknown");
}
static DEVICE_ATTR_RO(ccpin);

static struct attribute *typec_attrs[] = {
  &dev_attr_ccpin.attr,
  NULL,
};

static struct attribute_group typec_group = {
  .attrs = typec_attrs,
};

static int extcon_create_typec_sysfs(struct device *dev)
{
  int ret = 0;

  ret = sysfs_create_group(&dev->kobj, &typec_group);
  if (ret) {
    dev_info(dev, "typec ccpin node create fail \n");
    sysfs_remove_group(&dev->kobj, &typec_group);
    return ret;
  }

  return 0;
}

2、创建debugfs节点,然后封装file_operations 接口
这种方式一般是创建在debugfs下面
自己封装 file_operations 接口
static ssize_t xxx_debugfs_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
{
    return length;
}
static ssize_t xxx_debugfs_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset)
{
    struct device *dev = (struct device *)(file->f_inode->i_private);
    struct xxx_chip *data= dev_get_drvdata(dev);
    /* You need to make your own changes and confirm
    the regmap address location
    */
    struct regmap *regmap = data->data.regmap;
    char data_buffer[128], type = 0;
    unsigned int reg, reg_len, num;
    unsigned short value;
    ssize_t size;
    
    if (regmap == NULL) {
        dev_err(dev, "regmap is null, please init regmap\n");
        goto regmap_err;
    }
    size = simple_write_to_buffer(data_buffer, 128, offset, buffer, length);
    dev_err(dev, "data_buffer = %s\n", data_buffer);
    if ((data_buffer[0] != 'r') && (data_buffer[0] != 'w')) {
        dev_err(dev, "%s type error, please input 'r' or 'w'\n", __func__);
        goto type_err;
    }
    
    dev_err(dev, "write format:echo w [reg] [reg_val] [reg_len] [num] > xxx_file\n");
    dev_err(dev, "read format:echo r [reg] [reg_len] [num] > xxx_file\n");
    
    sscanf(data_buffer, "%c", &type);
    
    switch (type) {
        case 'r':
            sscanf(data_buffer, "%c %x %d %d", &type, &reg, &reg_len, &num);
    
            do {
                if (regmap_raw_read(regmap, reg, (void *)&value, reg_len)) {
                    dev_err(dev, "%s regmap_raw_read %d byte fail %d\n",
                            __func__, reg_len, __LINE__);
                    goto read_err;
                }
                dev_err(dev, "regmap_raw_read %d byte success value = 0x%x\n",
                        reg_len, value);
            } while(--num);
        break;
        case 'w':
            sscanf(data_buffer, "%c %x %hx %d %d", &type, &reg, &value, &reg_len, &num);
    
            do {
                if (regmap_raw_write(regmap, reg, (void *)&value, reg_len)) {
                    dev_err(dev, "%s regmap_raw_write %d byte fail %d\n",
                            __func__, reg_len, __LINE__);
                    goto write_err;
                }
                dev_err(dev, "regmap_raw_write %d byte success value = 0x%x\n",
                        reg_len, value);
            } while(--num);
        break;
    }

read_err:
write_err:
regmap_err:
type_err:
    return length;
}
static const struct file_operations xxx_debugfs_fops = {
    .read = xxx_debugfs_read,
    .write = xxx_debugfs_write,
};

static int xxx_debugfs_init(struct device *dev)
{
    struct dentry *debugfs_dir = NULL;
    int ret = 0;

    debugfs_dir = debugfs_create_dir(xxx_debugfs, NULL); //创建目录
    if (!debugfs_dir) {
        dev_err(dev, "%s create debug file system fail\n", __func__);
        ret = -1;
        goto debugfs_create_error;
    }

    debugfs_create_file(xxx_file, 0664,
            debugfs_dir, dev, &xxx_debugfs_fops); //创建文件

    dev_err(dev, "%s create debug file system success\n", __func__);
    return ret;

debugfs_create_error:
    return ret;
}

3、创建proc 节点,封装 proc_ops 
只需要封装open接口就可以 
static const struct proc_ops xxx_fops = {
    .proc_open = xxx_open,
    .proc_read = seq_read,
    .proc_lseek = seq_lseek
    .proc_release = single_release,
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个专注于USB的驱动工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值