/dev/zero のような /dev/one を作成するにはどうすればいいですか?

/dev/zero のような /dev/one を作成するにはどうすればいいですか?

連続した文字のストリームを生成するファイルを作成するにはどうすればよいでしょうか0x01? と同じです/dev/zeroが、選択した文字を生成します。

/dev/zero – 書き込まれたすべての入力を受け入れて破棄します。読み取り時に、出力としてヌル文字 (ゼロ値のバイト) の連続ストリームを生成します。

読み取り可能である必要がありますcat。名前付きパイプにループを実行することを検討しましたが、それにはアクティブなプロセスが必要です。

答え1

…しかし、それには積極的なプロセスが必要です。

オリジナル/dev/zeroも取り扱っていますアクティブな「プロセス」、 しかしカーネル内ユーザー空間レベルで処理したくない場合は、他の選択肢はかなり限られます。その場合はカーネル ドライバーを使用する必要があります。

答え2

trまあ、/dev/zeroをパイプしたり、他の方法でもできるだろう

# cat /dev/zero | tr '\000' '\001' | hexdump -C                                    
00000000  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
*

cat をスキップしてプロセス置換を使用する場合。

# hexdump -C <( tr '\000' '\001' </dev/zero ) 
00000000  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|

対。

# cat /dev/zero | hexdump -C
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*

答え3

恥ずかしげもなく改作Linux カーネル モジュール プログラミング ガイド

#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/poll.h>

/*  Prototypes - this would normally go in a .h file */
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char __user *, size_t,
                            loff_t *);

#define SUCCESS 0
#define DEVICE_NAME "one" /* Dev name as it appears in /proc/devices   */

/* Global variables are declared as static, so are global within the file. */

static int major; /* major number assigned to our device driver */

static struct class *cls;

static struct file_operations chardev_fops = {
    .read = device_read,
    .write = device_write,
    .open = device_open,
    .release = device_release,
};

static int __init chardev_init(void)
{
    major = register_chrdev(0, DEVICE_NAME, &chardev_fops);

    if (major < 0) {
        pr_alert("Registering char device failed with %d\n", major);
        return major;
    }

    pr_info("I was assigned major number %d.\n", major);

    cls = class_create(THIS_MODULE, DEVICE_NAME);
    device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);

    pr_info("Device created on /dev/%s\n", DEVICE_NAME);

    return SUCCESS;
}

static void __exit chardev_exit(void)
{
    device_destroy(cls, MKDEV(major, 0));
    class_destroy(cls);

    /* Unregister the device */
    unregister_chrdev(major, DEVICE_NAME);
}

/* Methods */

/* Called when a process tries to open the device file, like
 * "sudo cat /dev/chardev"
 */
static int device_open(struct inode *inode, struct file *file)
{
    try_module_get(THIS_MODULE);

    return SUCCESS;
}

/* Called when a process closes the device file. */
static int device_release(struct inode *inode, struct file *file)
{
    /* Decrement the usage count, or else once you opened the file, you will
     * never get rid of the module.
     */
    module_put(THIS_MODULE);

    return SUCCESS;
}

/* Called when a process, which already opened the dev file, attempts to
 * read from it.
 */
static ssize_t device_read(struct file *filp, /* see include/linux/fs.h   */
                           char __user *buffer, /* buffer to fill with data */
                           size_t length, /* length of the buffer     */
                           loff_t *offset)
{
    int i;

    for (i = 0; i < length; i++) {
      put_user('1', buffer + i);
    }

    /* Most read functions return the number of bytes put into the buffer. */
    return length;
}

/* Called when a process writes to dev file: echo "hi" > /dev/hello */
static ssize_t device_write(struct file *filp, const char __user *buff,
                            size_t len, loff_t *off)
{
    pr_alert("Sorry, this operation is not supported.\n");
    return -EINVAL;
}

module_init(chardev_init);
module_exit(chardev_exit);

MODULE_LICENSE("GPL");

メイクファイル

obj-m += onedev.o

PWD := $(CURDIR)

ifeq ($(CONFIG_STATUS_CHECK_GCC),y)
CC=$(STATUS_CHECK_GCC)
ccflags-y += -fanalyzer
endif

all:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build CC=$(CC) M=$(PWD) modules

clean:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build CC=$(CC) M=$(PWD) clean
    $(RM) other/cat_noblock *.plist

indent:
    clang-format -i *[.ch]
    clang-format -i other/*[.ch]

関連情報