杂项设备与虚拟设备:简化驱动开发的神器

Linux Swap 子系统:架构、内存管理与虚拟化 Swap Linux Swap机制通过将不活跃内存页移至磁盘或压缩内存,扩展系统有效内存容量,缓解内存压力。传统架构中,逻辑Swap槽与物理存储绑定,导致资源浪费,尤其在使用Zswap等压缩技术时。为此,Vswap与Xswap提出虚拟化方案:前者以XArray实现灵活映射,支持多后端迁移;后者采用稀疏映射,简化管理但容量固定。二者在架构设计、资源记账与动态扩展上各有权衡,反映了内核开发中对性能、可维护性与灵活性的深层考量。 阅读详情

一、顶级架构一句话总结

misc设备(简化字符设备) + 虚拟设备(无硬件依赖) = 快速原型开发

杂项设备简化了字符设备的注册流程,虚拟设备则无需真实硬件支持。


二、杂项设备(miscdevice)

什么是杂项设备?

┌─────────────────────────────────────────────────────────┐
│                 杂项设备特点                             │
├─────────────────────────────────────────────────────────┤
│  1. 主设备号固定为10,自动分配次设备号                   │
│  2. 简化注册流程,无需手动创建cdev                       │
│  3. 自动创建设备节点                                     │
│  4. 适合简单字符设备                                     │
└─────────────────────────────────────────────────────────┘

miscdevice结构

struct miscdevice {
    int minor;                              // 次设备号
    const char *name;                       // 设备名称
    const struct file_operations *fops;     // 文件操作
    struct list_head list;
    struct device *parent;
    struct device *this_device;
    const struct attribute_group **groups;
    const char *nodename;
    umode_t mode;
};

// 预定义的次设备号
#define MISC_DYNAMIC_MINOR  255  // 动态分配
#define PSMOUSE_MINOR       1    // PS/2鼠标
#define MS_BUSMOUSE_MINOR   2    // 总线鼠标
#define ATIXL_BUSMOUSE_MINOR 3   // ATI总线鼠标
#define WATCHDOG_MINOR      130  // 看门狗
#define TEMP_MINOR          131  // 温度传感器

API函数

#include <linux/miscdevice.h>

// 注册杂项设备
int misc_register(struct miscdevice *misc);

// 注销杂项设备
void misc_deregister(struct miscdevice *misc);

完整示例:简单LED控制

#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/gpio/consumer.h>

struct led_misc_data {
    struct miscdevice misc;
    struct gpio_desc *led_gpio;
};

static int led_open(struct inode *inode, struct file *file)
{
    struct led_misc_data *data = container_of(file->private_data, struct led_misc_data, misc);
    file->private_data = data;
    return 0;
}

static ssize_t led_write(struct file *file, const char __user *buf,
                         size_t count, loff_t *ppos)
{
    struct led_misc_data *data = file->private_data;
    char kbuf[2];

    if (count > 2)
        count = 2;

    if (copy_from_user(kbuf, buf, count))
        return -EFAULT;

    // 控制LED
    if (kbuf[0] == '0')
        gpiod_set_value(data->led_gpio, 0);
    else if (kbuf[0] == '1')
        gpiod_set_value(data->led_gpio, 1);

    return count;
}

static ssize_t led_read(struct file *file, char __user *buf,
                        size_t count, loff_t *ppos)
{
    struct led_misc_data *data = file->private_data;
    char state;

    state = gpiod_get_value(data->led_gpio) ? '1' : '0';

    if (copy_to_user(buf, &state, 1))
        return -EFAULT;

    return 1;
}

static long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    struct led_misc_data *data = file->private_data;

    switch (cmd) {
    case 0:
        gpiod_set_value(data->led_gpio, 0);
        break;
    case 1:
        gpiod_set_value(data->led_gpio, 1);
        break;
    case 2:
        gpiod_set_value(data->led_gpio, !gpiod_get_value(data->led_gpio));
        break;
    default:
        return -EINVAL;
    }

    return 0;
}

static const struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open = led_open,
    .read = led_read,
    .write = led_write,
    .unlocked_ioctl = led_ioctl,
};

static struct led_misc_data led_data = {
    .misc = {
        .minor = MISC_DYNAMIC_MINOR,
        .name = "myled",
        .fops = &led_fops,
        .mode = 0666,
    },
};

static int __init led_init(void)
{
    int ret;

    // 获取GPIO
    led_data.led_gpio = gpiod_get(NULL, "led", GPIOD_OUT_LOW);
    if (IS_ERR(led_data.led_gpio))
        return PTR_ERR(led_data.led_gpio);

    // 注册杂项设备
    ret = misc_register(&led_data.misc);
    if (ret) {
        gpiod_put(led_data.led_gpio);
        return ret;
    }

    pr_info("LED misc device registered: /dev/%s\n", led_data.misc.name);
    return 0;
}

static void __exit led_exit(void)
{
    misc_deregister(&led_data.misc);
    gpiod_put(led_data.led_gpio);
    pr_info("LED misc device unregistered\n");
}

module_init(led_init);
module_exit(led_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Driver Developer");

三、虚拟设备示例

虚拟串口

#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>

#define BUFFER_SIZE 4096

struct virtual_serial_data {
    struct miscdevice misc;
    char *buffer;
    int read_pos;
    int write_pos;
    struct mutex lock;
    wait_queue_head_t read_queue;
};

static int virtual_serial_open(struct inode *inode, struct file *file)
{
    struct virtual_serial_data *data = container_of(file->private_data, struct virtual_serial_data, misc);
    file->private_data = data;
    return 0;
}

static ssize_t virtual_serial_read(struct file *file, char __user *buf,
                                   size_t count, loff_t *ppos)
{
    struct virtual_serial_data *data = file->private_data;
    int available, ret;

    if (file->f_flags & O_NONBLOCK) {
        if (mutex_trylock(&data->lock) == 0)
            return -EAGAIN;
    } else {
        if (mutex_lock_interruptible(&data->lock))
            return -ERESTARTSYS;
    }

    while (data->read_pos == data->write_pos) {
        mutex_unlock(&data->lock);

        if (file->f_flags & O_NONBLOCK)
            return -EAGAIN;

        if (wait_event_interruptible(data->read_queue, data->read_pos != data->write_pos))
            return -ERESTARTSYS;

        if (mutex_lock_interruptible(&data->lock))
            return -ERESTARTSYS;
    }

    available = (data->write_pos - data->read_pos + BUFFER_SIZE) % BUFFER_SIZE;
    if (count > available)
        count = available;

    if (data->read_pos + count > BUFFER_SIZE) {
        int first_part = BUFFER_SIZE - data->read_pos;
        if (copy_to_user(buf, data->buffer + data->read_pos, first_part)) {
            ret = -EFAULT;
            goto out;
        }
        if (copy_to_user(buf + first_part, data->buffer, count - first_part)) {
            ret = -EFAULT;
            goto out;
        }
    } else {
        if (copy_to_user(buf, data->buffer + data->read_pos, count)) {
            ret = -EFAULT;
            goto out;
        }
    }

    data->read_pos = (data->read_pos + count) % BUFFER_SIZE;
    ret = count;

out:
    mutex_unlock(&data->lock);
    return ret;
}

static ssize_t virtual_serial_write(struct file *file, const char __user *buf,
                                    size_t count, loff_t *ppos)
{
    struct virtual_serial_data *data = file->private_data;
    int space, ret;

    if (mutex_lock_interruptible(&data->lock))
        return -ERESTARTSYS;

    space = (data->read_pos - data->write_pos - 1 + BUFFER_SIZE) % BUFFER_SIZE;
    if (count > space)
        count = space;

    if (data->write_pos + count > BUFFER_SIZE) {
        int first_part = BUFFER_SIZE - data->write_pos;
        if (copy_from_user(data->buffer + data->write_pos, buf, first_part)) {
            ret = -EFAULT;
            goto out;
        }
        if (copy_from_user(data->buffer, buf + first_part, count - first_part)) {
            ret = -EFAULT;
            goto out;
        }
    } else {
        if (copy_from_user(data->buffer + data->write_pos, buf, count)) {
            ret = -EFAULT;
            goto out;
        }
    }

    data->write_pos = (data->write_pos + count) % BUFFER_SIZE;
    wake_up_interruptible(&data->read_queue);
    ret = count;

out:
    mutex_unlock(&data->lock);
    return ret;
}

static const struct file_operations virtual_serial_fops = {
    .owner = THIS_MODULE,
    .open = virtual_serial_open,
    .read = virtual_serial_read,
    .write = virtual_serial_write,
};

static struct virtual_serial_data serial_data = {
    .misc = {
        .minor = MISC_DYNAMIC_MINOR,
        .name = "vserial",
        .fops = &virtual_serial_fops,
    },
};

static int __init virtual_serial_init(void)
{
    int ret;

    serial_data.buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
    if (!serial_data.buffer)
        return -ENOMEM;

    mutex_init(&serial_data.lock);
    init_waitqueue_head(&serial_data.read_queue);

    ret = misc_register(&serial_data.misc);
    if (ret) {
        kfree(serial_data.buffer);
        return ret;
    }

    pr_info("Virtual serial device registered: /dev/%s\n", serial_data.misc.name);
    return 0;
}

static void __exit virtual_serial_exit(void)
{
    misc_deregister(&serial_data.misc);
    kfree(serial_data.buffer);
    pr_info("Virtual serial device unregistered\n");
}

module_init(virtual_serial_init);
module_exit(virtual_serial_exit);

MODULE_LICENSE("GPL");

四、虚拟看门狗

#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/timer.h>

#define TIMEOUT_SEC 10

struct watchdog_data {
    struct miscdevice misc;
    struct timer_list timer;
    int timeout;
    bool enabled;
    struct mutex lock;
};

static void watchdog_timeout(struct timer_list *t)
{
    struct watchdog_data *data = from_timer(data, t, timer);

    pr_emerg("Watchdog timeout! System will reset.\n");
    // 实际产品中这里会触发系统重启
    // kernel_restart("watchdog timeout");
}

static int watchdog_open(struct inode *inode, struct file *file)
{
    struct watchdog_data *data = container_of(file->private_data, struct watchdog_data, misc);
    file->private_data = data;
    return 0;
}

static ssize_t watchdog_write(struct file *file, const char __user *buf,
                              size_t count, loff_t *ppos)
{
    struct watchdog_data *data = file->private_data;

    // 喂狗
    mutex_lock(&data->lock);
    if (data->enabled) {
        mod_timer(&data->timer, jiffies + data->timeout * HZ);
    }
    mutex_unlock(&data->lock);

    return count;
}

static long watchdog_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    struct watchdog_data *data = file->private_data;
    int ret = 0;

    mutex_lock(&data->lock);

    switch (cmd) {
    case WDIOC_GETSUPPORT:
        // 返回支持的功能
        break;
    case WDIOC_GETSTATUS:
        // 返回状态
        break;
    case WDIOC_KEEPALIVE:
        // 喂狗
        if (data->enabled) {
            mod_timer(&data->timer, jiffies + data->timeout * HZ);
        }
        break;
    case WDIOC_SETTIMEOUT:
        // 设置超时时间
        if (arg > 0 && arg <= 60) {
            data->timeout = arg;
            if (data->enabled) {
                mod_timer(&data->timer, jiffies + data->timeout * HZ);
            }
        } else {
            ret = -EINVAL;
        }
        break;
    case WDIOC_GETTIMEOUT:
        // 获取超时时间
        ret = data->timeout;
        break;
    default:
        ret = -ENOTTY;
    }

    mutex_unlock(&data->lock);
    return ret;
}

static int watchdog_release(struct inode *inode, struct file *file)
{
    struct watchdog_data *data = file->private_data;

    // 关闭时停止看门狗(或保持运行)
    mutex_lock(&data->lock);
    if (data->enabled) {
        del_timer(&data->timer);
        data->enabled = false;
    }
    mutex_unlock(&data->lock);

    return 0;
}

static const struct file_operations watchdog_fops = {
    .owner = THIS_MODULE,
    .open = watchdog_open,
    .write = watchdog_write,
    .unlocked_ioctl = watchdog_ioctl,
    .release = watchdog_release,
};

static struct watchdog_data watchdog_data = {
    .misc = {
        .minor = WATCHDOG_MINOR,
        .name = "watchdog",
        .fops = &watchdog_fops,
    },
    .timeout = TIMEOUT_SEC,
};

static int __init watchdog_init(void)
{
    int ret;

    mutex_init(&watchdog_data.lock);
    timer_setup(&watchdog_data.timer, watchdog_timeout, 0);

    ret = misc_register(&watchdog_data.misc);
    if (ret)
        return ret;

    pr_info("Watchdog device registered: /dev/%s\n", watchdog_data.misc.name);
    return 0;
}

static void __exit watchdog_exit(void)
{
    del_timer_sync(&watchdog_data.timer);
    misc_deregister(&watchdog_data.misc);
    pr_info("Watchdog device unregistered\n");
}

module_init(watchdog_init);
module_exit(watchdog_exit);

MODULE_LICENSE("GPL");

五、字符设备 vs 杂项设备对比

特性字符设备杂项设备
主设备号需要申请固定为10
注册复杂度高低
设备节点需手动创建自动创建
适用场景复杂设备简单设备

六、用户空间测试

# 查看杂项设备
ls /dev/ | grep -E "myled|vserial|watchdog"

# 测试LED
echo 1 > /dev/myled
echo 0 > /dev/myled

# 测试虚拟串口
cat /dev/vserial &
echo "hello" > /dev/vserial

# 测试看门狗
echo "keepalive" > /dev/watchdog

七、终极总结

杂项设备 = 简化字符设备开发的利器

  • 核心优势:自动分配设备号、自动创建节点
  • 适用场景:简单字符设备、虚拟设备
  • 虚拟设备:无需真实硬件,适合测试和原型开发

掌握杂项设备,快速实现驱动原型!

『言善信』Fiddler工具 — 1、Fiddler介绍与安装 文章目录1、Fiddler简介2、Fiddler功能3、Fiddler工作原理4、Fiddler安装 1、Fiddler简介 Fiddler是强大的抓包工具之一,它能记录所有客户端和服务器之间的HTTP和HTTPS请求,是web调试的利器。 Fiddler是位于客户端和服务端之间的HTTP代理,它的原理是以web代理服务器的形式进行工作的,使用的代理地址是:127.0.0.1,端口默认为8888,我们也可以通过设置进行修改。 Fiddler可以抓取支持HTTP代理的任意程序的数据包,如果要抓取https会 阅读详情

相关推荐

国产SR8201F以太网PHY芯片调试避坑指南:从机贴失败到杜邦线救场的实战记录

本文详细介绍了国产SR8201F以太网PHY芯片的调试避坑指南,涵盖硬件设计、PCB布局、SMT贴片及软件驱动等关键环节。通过实战案例解析,帮助工程师解决MII/RMII接口配置、电源设计、信号完整性等典型问题,提升以太网通信稳定性与EMC性能。

c6d7e8f9g的博客 1212

理解 Linux 动态库加载:LD_LIBRARY_PATH

flyfish

二分掌柜的 331

【AI平台】n8n入门2:第一个工作流,调用本地大模型

n8n是一款开源的,专注于AI工作流构建,支持灵活的自定义与集成。就是可以把大模型和其他工具联合起来,这就厉害了。而且,免费功能又强大,目前很火,来研究一下。

正经教主是个热衷于正经学习分享的教主。 4531

Linux 磁盘满了怎么排查?df / du / find 三步定位大文件

Linux 磁盘满排查三步法:df -h 定位分区、du 逐层下钻、find 按大小和时间抓大文件,附 inode 耗尽、文件已删未释放、du 与 df 不一致等经典坑的解决方案。

weixin_38291577的博客 218

信息收集-服务器信息

服务器上面可以运行大量的系统服务和第三方应用服务,如果操作系统或者第三方软件没有及时升级打补丁,攻击者就有可能直接通过服务器上运行的服务进行攻击。

weixin_49349476的博客 1446

STM32 Nucleo-144开发板开箱bring-up

最近做项目,用到STM32F446ZET6这款MCU,为了赶进度,前期软件需要提前开发,于是在某宝买了对应主控的官方开发板,为了避免遗忘,后面能翻出来回忆一些细节,就形成了本篇的主要内容,同时也希望能够帮助刚上手的小伙伴少走弯路,如果对你有帮助请点赞、收藏、转发,谢谢!

汽车电子软件领域知识分享 2674

Linux-iostat命令详解

Linux命令学习记录

m0xin的博客 98

GCJ02坐标系转WGS84坐标系(已实地测试基本无偏差)

坐标系转化,GCJ02坐标系,WGS84坐标系

Xiao_XianYu_的博客 1854

Linux 服务器性能排查手册(2026):CPU、内存、磁盘IO、网络四大瓶颈定位

iptables 四表五链模型、firewalld zone 信任级别、云安全组与主机防火墙的关系与优先级,避坑改了防火墙把自己挡在服务器外面的翻车事故。

2502_91473995的博客 287

Ansys Lumerical FDTD仿真加速策略与高性能硬件选型指南

本文深入探讨了Ansys Lumerical FDTD仿真的核心加速策略,涵盖算法优化与硬件选型两大维度。通过合理运用非均匀网格、对称边界条件等算法技巧,并精准匹配CPU/GPU计算资源与高性能硬件配置,可显著提升仿真效率,将计算时间从数天缩短至数小时。

a0b1c2d3的专栏 606

16、保障Azure应用安全:密钥管理与身份认证

本文深入探讨了保障Azure应用安全的关键措施,包括使用网络安全工具(如Application Gateway和Azure Front Door)防范攻击,解决传统密钥和机密存储方式的安全隐患,以及通过Azure Key Vault实现敏感信息的安全管理。同时,介绍了使用托管标识实现Azure资源间安全访问的方法,并结合实际操作步骤展示了如何配置Key Vault、设置访问策略、存储机密以及授予Web应用对SQL Server的访问权限。最后,对不同安全措施进行了比较,并提出了在开发、测试及生产环境中的综合

rock5的博客 71

【Linux】APT 本地 deb 安装与 `-f` 参数总结笔记

apt install ./xx.deb 可自动解析并安装依赖,无需 -f;-f 仅用于修复已损坏的依赖状态,非首次安装时必需。apt install -f 可单独运行,修复 broken dependencies。两者职责不同:前者是安装与依赖解决,后者是故障修复。完全离线时需提前准备依赖包或本地源。

hknaruto的专栏 209

Android性能优化之Android Profiler

在移动应用开发中,打造一个流畅、省电且不卡顿的用户体验是至关重要的。然而,随着应用功能的日益复杂,内存泄漏、CPU暴涨、网络卡顿以及电量消耗过快等问题常常化身为隐形杀手,悄悄吞噬着用户体验。为了帮助开发者精准定位并解决这些性能瓶颈,谷歌在Android Studio中集成了一款强大的一站式性能分析工具Android Profiler。Android Profiler作为Android Studio内置的实时数据可视化工具,支持运行在Android 5.0及更高版本的设备上。

xiangzhihong8的专栏 200

Linux rm 误删文件恢复实操教程

Linux使用rm删除文件时,并不会直接抹除磁盘上的数据,只是移除文件索引,让系统不再识别这块空间。只要没有写入新数据,原有扇区内容就会保留。新文件写入才有可能覆盖这些区域,一旦覆盖就很难找回。恢复的本质就是扫描磁盘,找到这些还存在、但索引丢失的数据条目,再把它们导出保存到其他分区。越早停止写入,恢复成功的概率越高。

海天数据恢复-winhex数据恢复教程 225

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Linux sudo

如果输出 → 无 sudo 权限 如果输出 → 拥有全部 sudo 权限 辅助验证命令 ⚠️ 注意:在 wheel 组 ≠ 一定能 sudo,必须 开启 Ubuntu/Debian: ✅ 重要:修改组之后,用户要重新登录才生效! 或者执行 临时生效 看到这行(没有 #注释)才生效: 方式 2:visudo 直接单独给用户授权(精细化权限) 找到 ,下面添加一行: 自带语法校验,写错会告警,不要直接 vim 改 ,写错直接 sudo 炸掉! 想免密 su

fengliyang_的博客 178

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Linux 磁盘 100% 但 du 查不出东西,五种情况逐个排

监控告警说根分区 100%,登录上去 du -sh /* 加起来只有 12GB,df 显示 40GB 已用。差了快 30GB,du 找不到任何东西。这种情况基本都是"文件被删了但进程还开着",但也可能是别的原因。这篇按可能性排一下顺序。

2408_89646393的博客 163

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Windows/Linux下强实时运动控制内核(二):基于Qt的Delta机械手的开发应用

强实时运动控制内核MotionRT750下Qt开发Delta机械手的完整开发流程。

weixin_57350300的博客 240

Linux 网络基础详解:IP、子网、路由与 ip、ss 命令实战

建库建表、增删改查、连接查询(内连左连右连)、聚合函数、权限控制 GRANT/REVOKE,每条命令配可运行示例,零基础也能跟着敲会 SQL 基础。

2502_91473995的博客 610

Linux、Shell、MySQL 测试卷逐题细讲(下篇:MySQL)

本文为Linux、Shell、MySQL测试卷下半段MySQL部分逐题讲解,包含填空、选择与SQL分析三类题型。填空题覆盖COUNT、HAVING、DISTINCT、事务、约束、索引等核心语法;选择题辨析存储过程、索引类型、ACID、存储引擎、用户管理等考点。SQL大题围绕员工、部门、职位、地点四张关联表,考察多表连接、分组聚合、自连接、相关子查询、NULL处理等高频写法,标注LEFT JOIN统计计数、NULL判断、子查询别名等易错坑点,同时梳理试卷OCR识别带来的干扰问题,重点提示SQL实操中的常见失误

dongziwen1的博客 181

Linux 下 OpenCode 接入自定义大模型 API 教程:以 DeepSeek-V4.1-Flash-1017 为例

本文介绍在Linux下通过Python脚本配置OpenCode接入自定义大模型API(以DeepSeek-V4.1-Flash-1017为例),实现永久化、非侵入式配置。通过修改~/.config/opencode/opencode.json文件,添加OpenAI兼容服务商BLSC,注册模型并设置APIKey。支持命令行测试、默认模型设定及安全权限控制,操作简单且不影响原有配置。适用于各类支持OpenAI接口的自定义模型服务,提升开发灵活性与安全性。

qq_15060477的博客 122

【Linux 命令实战(02):文件与目录操作,掌握 pwd、ls、cd 三个核心命令】

命令作用cd /进入根目录cd ~进入当前用户家目录cd返回当前用户家目录cd …返回上一级目录cd …/…返回上两级目录cd -返回上一次所在目录进入指定目录命令核心用途常用参数pwd查看当前目录-L、-Pls查看文件和目录cd切换目录…、~、-Linux 文件系统的基本结构。绝对路径与相对路径的区别。Tab 自动补全。Shell 通配符。使用&&组合命令。这篇文章主要解决的是如何在 Linux 文件系统中快速定位目录。

一些微不足道的见解、希望能帮助各位 192

Linux Day29——HTTP与网络排障

*实测**:`traceroute -n -m 8 8.8.8.8` 的输出:第 1 跳 `172.17.144.1`(本机网关)、第 2 跳 `10.32.0.1`、第 3 跳 `10.50.255.253`、第 4 跳 `* * *`、第 5 跳 `221.226.71.193`、第 6 跳 `* * *`、第 7、8 跳有地址但夹着星号。`ping` 和 `traceroute` 都靠它。**实测**:`ss -lta` 看到三行 `domain`,加 `-n` 后变成 `53`。

2503_94114317的博客 151

【Linux】进程间通信的基础概念及基于匿名管道的进程池

前面我们介绍了进程的创建、退出和等待,接下来看看进程之间怎样传递数据。这篇从匿名管道入手,再用管道把父子进程联系起来,写一个简单的进程池小demo。而且我把发行版从CentOS切换成Ubuntu了,主要是CentOS已经不维护了,可惜了。。。

qeen87的博客 316

Linux的渲染与显示系统链路

Linux渲染与显示链路核心为DRM/KMS + EGL直连模式,绕过传统X11/Wayland中间层,实现低延迟、高效率的直接帧提交。相比X11的粗粒度权限控制与Wayland的合成开销,该方案链路短、资源消耗低,但仅支持单进程独占显示,缺乏窗口管理与系统级兜底。EGL作为跨平台桥梁,连接OpenGL ES与原生显示系统,通过Display、Surface、Context三要素构建渲染环境。内核层DRM管理GPU资源,KMS配置显示模式,用户态GDM负责登录会话,共同构成从硬件到应用的完整图形栈。

微小的鱼的博客 205

Linux 启动流程与故障修复:GRUB、systemd 与救援模式实战

密钥登录配置替代密码、sshd_config 禁 root 禁密码改端口、fail2ban 自动封爆破 IP、端口改不改的权衡,服务器被扫描爆破时的完整加固方案。

2502_91473995的博客 459

芯参谋(88):Linux 嵌入式系统开发指南

本文为面向MPU/Linux平台的用户态系统层开发指南,聚焦启动链各环节的可测量、可判据化工程实践。涵盖交叉工具链一致性、Bootloader交接、根文件系统构建与瘦身、init/systemd服务编排、进程与IO模型、网络接入、调试可观测性、实时性优化、安全加固、电源管理及OTA升级等核心内容。强调“启动时间、镜像大小、内存峰值、断电恢复”等量化指标,提出四条读者路径:从零搭建、启动优化、线上问题排查、实时性实现。以Linux 6.1/LTS内核、glibc2.36/musl1.2、systemd252等

qq520131714的专栏 465
上一篇: 输入子系统开发实战:键盘鼠标触摸屏
下一篇: 内核调试技术全攻略:从printk到KGDB
LinuxRos
博客等级 码龄5年 11粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值