LINUX.ORG.RU

Избранные сообщения LamerOk

block device driver: не работает чтение

Форум — Development

Ядро: 5.15.0-70-generic.

Я раньше (параметр is_remap=0) в подобной задаче при получении входного запроса bio, формировал свой запрос bio к вышестоящему устройству, и всё работало. Но медленно. Скорость записи на флешку была ~460 kb/sec. Потом я решил пробрасывать запрос bio вышестоящему устройству напрямую (is_remap=1). Если при этом не пытаться модифицировать данные, то всё работает, и скорость возрастает до 1.8 мб/сек т.е. ~ в 4 раза. Но если начать модифицировать данные (а это нужно), то работает только запись. При чтении, dd получает нерасшифрованные данные, а bio в stackbd_end_io_read_cloned (перед этим клонированный с помощью bio_clone_fast в stackbd_io_fn_remap) вообще имеет нулевой размер. При этом размер obio ненулевой. Как такое вообще происходит, и как сделать правильно?

Интересно, что если в stackbd_end_io_read_cloned менять данные после вызова bio_endio, то в dd прилетают расшифрованные данные, но чую, что так делать не правильно. Что подтверждается тем, что fsck после mkfs вешает систему.

Вот, например, я читаю сектор:

user@astra-1:~/git/stackbd/module$ sudo dd if=/dev/stackbd0 count=1 | hexdump -C
00000000  63 d0 18 e5 e3 ee fb a6  ee e9 fc 88 8a a8 a8 88  |c...............|
00000010  8a 88 88 88 88 70 88 88  98 88 8c 88 88 88 88 88  |.....p..........|
00000020  88 48 26 8b 88 b3 88 88  88 88 88 88 8a 88 88 88  |.H&.............|
00000030  89 88 8e 88 88 88 88 88  88 88 88 88 88 88 88 88  |................|
00000040  08 88 a1 57 55 08 9b c6  c7 a8 c6 c9 c5 cd a8 a8  |...WU...........|
00000050  a8 a8 ce c9 dc bb ba a8  a8 a8 86 97 36 ff f4 24  |............6..$|
00000060  aa 48 fc 83 de 3c 86 33  8f 88 45 98 d6 63 78 ba  |.H...<.3..E..cx.|
00000070  6c 45 9e 45 91 63 76 dc  e0 e1 fb a8 e1 fb a8 e6  |lE.E.cv.........|
00000080  e7 fc a8 e9 a8 ea e7 e7  fc e9 ea e4 ed a8 ec e1  |................|
00000090  fb e3 a6 a8 a8 d8 e4 ed  e9 fb ed a8 e1 e6 fb ed  |................|
000000a0  fa fc a8 e9 a8 ea e7 e7  fc e9 ea e4 ed a8 ee e4  |................|
000000b0  e7 f8 f8 f1 a8 e9 e6 ec  85 82 f8 fa ed fb fb a8  |................|
000000c0  e9 e6 f1 a8 e3 ed f1 a8  fc e7 a8 fc fa f1 a8 e9  |................|
000000d0  ef e9 e1 e6 a8 a6 a6 a6  a8 85 82 88 88 88 88 88  |................|
000000e0  88 88 88 88 88 88 88 88  88 88 88 88 88 88 88 88  |................|
*
000001f0  88 88 88 88 88 88 88 88  88 88 88 88 88 88 dd 22  |..............."|
1+0 записей получено
1+0 записей отправлено
512 байт скопировано, 0,0063565 s, 80,5 kB/s
00000200
user@astra-1:~/git/stackbd/module$

И вот, что вижу в логе:

Jun  9 15:24:11 astra-1 kernel: stackbd [task=00000000c60564d5] stackbd_io_fn_remap: HIT.r.1
Jun  9 15:24:11 astra-1 kernel: debugbd [task=00000000c60564d5] debugbd_submit_bio: debugbd: make request read  block 0            #pages 0    total-size 16384     
Jun  9 15:24:11 astra-1 kernel: stackbd [task=00000000c60564d5] stackbd_io_fn_remap: HIT.r.2
Jun  9 15:24:11 astra-1 kernel: stackbd [task=0000000089abc07d] stackbd_end_io_read_cloned: HIT.1
Jun  9 15:24:11 astra-1 kernel: stackbd [task=0000000089abc07d] stackbd_end_io_read_cloned: HIT.2: obio.size=16384; bio.size=0
Jun  9 15:24:11 astra-1 kernel: stackbd [task=0000000089abc07d] stackbd_end_io_read_cloned: HIT.3
Jun  9 15:24:11 astra-1 kernel: stackbd [task=0000000089abc07d] stackbd_end_io_read_cloned: HIT.4
Jun  9 15:24:11 astra-1 kernel: stackbd [task=00000000c60564d5] stackbd_io_fn_remap: HIT.r.1
Jun  9 15:24:11 astra-1 kernel: debugbd [task=00000000c60564d5] debugbd_submit_bio: debugbd: make request read  block 32           #pages 0    total-size 32768     
Jun  9 15:24:11 astra-1 kernel: stackbd [task=00000000c60564d5] stackbd_io_fn_remap: HIT.r.2
Jun  9 15:24:11 astra-1 kernel: stackbd [task=0000000089abc07d] stackbd_end_io_read_cloned: HIT.1
Jun  9 15:24:11 astra-1 kernel: stackbd [task=0000000089abc07d] stackbd_end_io_read_cloned: HIT.2: obio.size=32768; bio.size=0
Jun  9 15:24:11 astra-1 kernel: stackbd [task=0000000089abc07d] stackbd_end_io_read_cloned: HIT.3

debugbd - это тот же драйвер, только выводящий информацию о запросах, для отладки.

Исходный код драйвера stackbd:

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>

#include <linux/version.h>
#include <linux/kernel.h> // printk()
#include <linux/fs.h>     // everything...
#include <linux/errno.h>  // error codes
#include <linux/types.h>  // size_t
#include <linux/vmalloc.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/kthread.h>

#include <trace/events/block.h>

#include "logging.h"
#include "../common/stackbd.h"

#define STACKBD_BDEV_MODE (FMODE_READ | FMODE_WRITE | FMODE_EXCL)

#define KERNEL_SECTOR_SHIFT 9
#define KERNEL_SECTOR_SIZE (1 << KERNEL_SECTOR_SHIFT)

#define DECLARE_BIO_VEC struct bio_vec
#define ACCESS_BIO_VEC(x) (x)
#define DECLARE_BVEC_ITER struct bvec_iter
#define BIO_SET_SECTOR(bio, sec) (bio)->bi_iter.bi_sector = (sec)
#define BIO_GET_SECTOR(bio) (bio)->bi_iter.bi_sector
#define BIO_GET_SIZE(bio) (bio)->bi_iter.bi_size
#define BIO_SET_BDEV(bio, bdev) bio_set_dev((bio), (bdev));

//#ifdef CONFIG_LBDAF
#define SEC_FMT "llu"
//#else
//#define SEC_FMT "lu"
//#endif

MODULE_LICENSE("Dual BSD/GPL");

static int major_num = 0;
module_param(major_num, int, 0);
static int LOGICAL_BLOCK_SIZE = 512;
module_param(LOGICAL_BLOCK_SIZE, int, 0);
static bool is_remap = false;
module_param(is_remap, bool, 0);

typedef struct
{
	char path[PATH_MAX];
    fmode_t mode; // используется в aldcc_start / aldcc_stop
	bool is_bdev_raw_ok;
	struct block_device *bdev_raw;
} stackbd_target_t;

/*
 * The internal representation of our device.
 */
static struct stackbd_t {
    sector_t capacity; /* Sectors */
    struct gendisk *gd;
    spinlock_t lock;
    struct bio_list bio_list;
    struct task_struct *thread;
    int is_active;
    stackbd_target_t tgt;
    /* Our request queue */
    struct request_queue *queue;
} stackbd;

static DECLARE_WAIT_QUEUE_HEAD(req_event);

typedef void (* t_stackbd_io_fn)(struct bio *);
static t_stackbd_io_fn p_stackbd_io_fn = NULL;
static struct bio_set bs;

int buffer_read(
	struct stackbd_t *dev,
    unsigned long sector,
    unsigned long nsect,
    char *buffer
)
{
    int result = 0;
    unsigned nsize = nsect << KERNEL_SECTOR_SHIFT;
    int npages = ((nsize - 1) >> PAGE_SHIFT) + 1;
    struct bio *bio;
    struct block_device *bdev = dev->tgt.bdev_raw;

    //PINFO("begin; sector=%ld; nsect=%ld; buffer=%p\n", sector, nsect, buffer);

    if(unlikely(!dev->tgt.is_bdev_raw_ok))
    {
        PERROR("bdev is NULL!\n");
        result = -EFAULT;
        goto out;
    }

    bio = bio_alloc(GFP_NOIO, npages);

    if(unlikely(!bio))
    {
        PERROR("bio_alloc failed!\n");
        result = -ENOMEM;
        goto out;
    }

    BIO_SET_BDEV(bio, bdev);
    BIO_SET_SECTOR(bio, sector);

    bio_set_op_attrs(bio, REQ_OP_READ, REQ_PREFLUSH);

    {
        char *ptr = buffer;
        do
        {
            struct page *page;
            page = virt_to_page(ptr);
            if(unlikely(!page))
            {
                PERROR("virt_to_page failed!\n");
                result = -ENOMEM;
                break;
            }

            {
                unsigned op = offset_in_page(ptr);
                unsigned this_step = min((unsigned)(PAGE_SIZE - op), nsize);
                bio_add_page(bio, page, this_step, op);
                nsize -= this_step;
                ptr += this_step;
            }
        } while(nsize > 0);

        if(likely(!result))
        {
            result = submit_bio_wait(bio);
        }
        bio_put(bio);
    }
out:
    //PINFO("end (%d)\n", result);
    return result;
}

int buffer_write(
    struct stackbd_t *dev,
    unsigned long sector,
    unsigned long nsect,
    char *buffer
)
{
    int result = 0;
    unsigned nsize = nsect << KERNEL_SECTOR_SHIFT;
    int npages = ((nsize - 1) >> PAGE_SHIFT) + 1;
    struct bio *bio;
    struct block_device *bdev = dev->tgt.bdev_raw;

    //PINFO("begin; sector=%ld; nsect=%ld; buffer=%p\n", sector, nsect, buffer);

    if(unlikely(!dev->tgt.is_bdev_raw_ok))
    {
        PERROR("bdev is NULL!\n");
        result = -EFAULT;
        goto out;
    }

    bio = bio_alloc(GFP_NOIO, npages);
    if(unlikely(!bio))
    {
        PERROR("bio_alloc failed!\n");
        result = -ENOMEM;
        goto out;
    }
    BIO_SET_BDEV(bio, bdev);
    BIO_SET_SECTOR(bio, sector);

    bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_PREFLUSH);

    {
        char *ptr = buffer;
        do
        {
            struct page *page = virt_to_page(ptr);

            if(unlikely(!page))
            {
                PERROR("alloc page failed!\n");
                result = -ENOMEM;
                break;
            }

            {
                unsigned op = offset_in_page(ptr);
                unsigned this_step = min((unsigned)(PAGE_SIZE - op), nsize);
                bio_add_page(bio, page, this_step, op);
                nsize -= this_step;
                ptr += this_step;
            }
        } while(nsize > 0);

        if(likely(!result))
        {
	#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
            result = submit_bio_wait(bio);
	#else
            result = submit_bio_wait(WRITE | REQ_FLUSH, bio);
	#endif
        }
        bio_put(bio);
    }
out:
    //PINFO("end (%d)\n", result);
    return result;
}

static void stackbd_end_io_read_cloned(struct bio *bio)
{
    struct bio *obio = bio->bi_private;
    PINFO("HIT.1");
    if (bio_data_dir(bio) == READ)
    {
        DECLARE_BIO_VEC bvec;
        DECLARE_BVEC_ITER iter;

        PINFO("HIT.2: obio.size=%u; bio.size=%u", BIO_GET_SIZE(obio), BIO_GET_SIZE(bio));

        bio_for_each_segment(bvec, bio, iter)
        {
            char *p = page_address(ACCESS_BIO_VEC(bvec).bv_page) + ACCESS_BIO_VEC(bvec).bv_offset;
            int len = ACCESS_BIO_VEC(bvec).bv_len;
            int i;

            print_hex_dump(KERN_INFO, "readed data (1-st 16 bytes) ", DUMP_PREFIX_OFFSET, 16, 1, p, 16, false);

            for(i = 0; i < len; i++)
            {
                //*p++ ^= 0x12345678;
                *p++ ^= 0x88;
            }

            //p += len;
        }
        PINFO("HIT.3");
        bio_put(bio);
        bio_endio(obio);
    }
    else
    {
        bio_put(bio);
        bio_endio(obio);
    }
    //bio_put(bio);
    PINFO("HIT.4");
}

static void stackbd_io_fn_remap(struct bio *bio)
{
    DECLARE_BIO_VEC bvec;
    DECLARE_BVEC_ITER iter;
    struct bio *cbio = bio_clone_fast(bio, GFP_NOIO, &bs);

    BIO_SET_BDEV(cbio, stackbd.tgt.bdev_raw);
    cbio->bi_end_io = stackbd_end_io_read_cloned;
    cbio->bi_private = bio;
    //submit_bio_noacct(cbio);

    //trace_block_bio_remap(/*bdev_get_queue(stackbd.bdev_raw), */bio,
    //    stackbd.tgt.bdev_raw->bd_dev, BIO_GET_SECTOR(bio));

    if (bio_data_dir(bio) == READ)
    {
        PINFO("HIT.r.1");
        submit_bio_noacct(cbio);
        PINFO("HIT.r.2");
    }
    else
    {
        PINFO("HIT.w.1");
        bio_for_each_segment(bvec, cbio, iter)
        {
            char *p = page_address(ACCESS_BIO_VEC(bvec).bv_page) + ACCESS_BIO_VEC(bvec).bv_offset;
            int len = ACCESS_BIO_VEC(bvec).bv_len;
            int i;

            for(i = 0; i < len; i++)
            {
                // *p++ ^= 0x12345678;
                *p++ ^= 0x88;
            }

            print_hex_dump(KERN_INFO, "writed data (1-st 16 bytes) ", DUMP_PREFIX_OFFSET, 16, 1, p, 16, false);

            //p += len;
        }
        PINFO("HIT.w.2");
        submit_bio_noacct(cbio);
        PINFO("HIT.w.3");
    }
}

static void my_bio_complete(struct bio *bio, int ret)
{
    if (ret)
        bio_io_error(bio);
    else
        bio_endio(bio);
}

static void stackbd_io_fn_clone(struct bio *bio)
{
    int res;
    DECLARE_BIO_VEC bvec;
    DECLARE_BVEC_ITER iter;
    sector_t sector = BIO_GET_SECTOR(bio);
    int size = BIO_GET_SIZE(bio);
    int nsect = size >> KERNEL_SECTOR_SHIFT;
    char *src, *p;

    do
    {
		if (bio_data_dir(bio) == READ)
		{
			p = src = kmalloc(size, GFP_KERNEL);
			if (!src)
			{
				PERROR("Unable to allocate read buffer!\n");
				res = -ENOMEM;
				break;
			}

			do
			{
				res = buffer_read(&stackbd, sector, nsect, src);
				if (unlikely(res))
				{
					PERROR("i/o error while read!\n");
					break;
				}

				bio_for_each_segment(bvec, bio, iter)
				{
					char *dst = page_address(ACCESS_BIO_VEC(bvec).bv_page) + ACCESS_BIO_VEC(bvec).bv_offset;
					int len = ACCESS_BIO_VEC(bvec).bv_len;
					memcpy(dst, p, len);
					p += len;
				}
			}
			while (0);
		}
		else
		{
			p = src = kmalloc(size, GFP_KERNEL);
			if (!src)
			{
				PERROR("Unable to allocate write buffer!\n");
				res = -ENOMEM;
				break;
			}

			bio_for_each_segment(bvec, bio, iter)
			{
				char *dst = page_address(ACCESS_BIO_VEC(bvec).bv_page) + ACCESS_BIO_VEC(bvec).bv_offset;
				int len = ACCESS_BIO_VEC(bvec).bv_len;
				memcpy(p, dst, len);
				p += len;
			}
			res = buffer_write(&stackbd, sector, nsect, src);
			if (unlikely(res))
			{
				PERROR("i/o error while write!\n");
			}
		}
		kfree(src);
    }
    while (0);

    my_bio_complete(bio, res);
} // stackbd_io_fn_clone

static int stackbd_threadfn(void *data)
{
    struct bio *bio;

    set_user_nice(current, -20);

    while (!kthread_should_stop())
    {
        /* wake_up() is after adding bio to list. No need for condition */ 
        wait_event_interruptible(req_event, kthread_should_stop() ||
                !bio_list_empty(&stackbd.bio_list));

        spin_lock_irq(&stackbd.lock);
        if (bio_list_empty(&stackbd.bio_list))
        {
            spin_unlock_irq(&stackbd.lock);
            continue;
        }

        bio = bio_list_pop(&stackbd.bio_list);
        spin_unlock_irq(&stackbd.lock);

        p_stackbd_io_fn(bio);
    }

    return 0;
}

// Handle an I/O request.
static blk_qc_t stackbd_submit_bio(struct bio *bio)
{
    /*PINFO("stackbd: make request %-5s block %-12" SEC_FMT " #pages %-4hu total-size %-10u\n",
        bio_data_dir(bio) == WRITE ? "write" : "read",
        BIO_GET_SECTOR(bio),
        bio->bi_vcnt,
        BIO_GET_SIZE(bio)
    );*/

    spin_lock_irq(&stackbd.lock);
    if (!stackbd.tgt.bdev_raw)
    {
        PERROR("Request before bdev_raw is ready, aborting\n");
        goto abort;
    }
    if (!stackbd.is_active)
    {
        PERROR("Device not active yet, aborting\n");
        goto abort;
    }
    bio_list_add(&stackbd.bio_list, bio);
    wake_up(&req_event);
    spin_unlock_irq(&stackbd.lock);

    goto exit;

abort:
    spin_unlock_irq(&stackbd.lock);
    PERROR("<%p> Abort request\n", bio);
    bio_io_error(bio);
exit:
    return BLK_QC_T_NONE;
}

static int stackbd_target_open(stackbd_target_t *p_tdev)
{
    int res = 0;
    char *path = p_tdev->path;

    PINFO("Open %s\n", path);
    {
        struct block_device *bdev_raw = blkdev_get_by_path(path, p_tdev->mode, p_tdev);
        p_tdev->bdev_raw = bdev_raw;

        if (unlikely(IS_ERR(bdev_raw)))
        {
            res = PTR_ERR(bdev_raw);
            PINFO("error opening raw device %s <%d>\n", path, res);
        }

        p_tdev->is_bdev_raw_ok = !res;
        return res;
    }
}

static void stackbd_target_close(stackbd_target_t *p_tdev)
{
    if (p_tdev->is_bdev_raw_ok)
    {
        blkdev_put(p_tdev->bdev_raw, p_tdev->mode);
        p_tdev->bdev_raw = NULL;
        p_tdev->is_bdev_raw_ok = false;
    }
}

static int stackbd_start(char dev_path[])
{
    unsigned max_sectors;
    sector_t lba;

    stackbd_target_t *p_tgt = &stackbd.tgt;
    strcpy(p_tgt->path, dev_path);
    p_tgt->mode = STACKBD_BDEV_MODE;

    if(stackbd_target_open(p_tgt) < 0)
    {
        PERROR("Error while stackbd_target_open(..)!");
        return -EFAULT;
    }

    /* Set up our internal device */
    lba = i_size_read(p_tgt->bdev_raw->bd_inode) >> KERNEL_SECTOR_SHIFT;

    stackbd.capacity = lba;//get_capacity(stackbd.bdev_raw->bd_disk);
    PINFO("Device real capacity: %" SEC_FMT "\n", stackbd.capacity);

    set_capacity(stackbd.gd, stackbd.capacity);

    max_sectors = queue_max_hw_sectors(bdev_get_queue(p_tgt->bdev_raw));
    blk_queue_max_hw_sectors(stackbd.queue, max_sectors);
    PINFO("Max sectors: %u\n", max_sectors);

    stackbd.thread = kthread_create(stackbd_threadfn, NULL,
           stackbd.gd->disk_name);
    if (IS_ERR(stackbd.thread))
    {
        PERROR("error kthread_create <%lu>\n", PTR_ERR(stackbd.thread));
        goto error_after_bdev;
    }

    PINFO("done initializing successfully\n");
    stackbd.is_active = 1;
    wake_up_process(stackbd.thread);

    return 0;

error_after_bdev:
    stackbd_target_close(p_tgt);

    return -EFAULT;
}

static int stackbd_ioctl(struct block_device *bdev, fmode_t mode,
		     unsigned int cmd, unsigned long arg)
{
    char dev_path[80];
    void __user *argp = (void __user *)arg;

    switch (cmd)
    {
    case STACKBD_DO_IT:
        PINFO("\n*** DO IT!!!!!!! ***\n\n");

        if (copy_from_user(dev_path, argp, sizeof(dev_path)))
            return -EFAULT;

        return stackbd_start(dev_path);
    default:
        return -ENOTTY;
    }
}

/*
 * The HDIO_GETGEO ioctl is handled in blkdev_ioctl(), which
 * calls this. We need to implement getgeo, since we can't
 * use tools such as fdisk to partition the drive otherwise.
 */
int stackbd_getgeo(struct block_device * block_device, struct hd_geometry * geo)
{
	long size;

	/* We have no real geometry, of course, so make something up. */
	size = stackbd.capacity * (LOGICAL_BLOCK_SIZE / KERNEL_SECTOR_SIZE);
	geo->cylinders = (size & ~0x3f) >> 6;
	geo->heads = 4;
	geo->sectors = 16;
	geo->start = 0;
	return 0;
}

/*
 * The device operations structure.
 */
static struct block_device_operations stackbd_ops = {
    .owner  = THIS_MODULE,
    .submit_bio = stackbd_submit_bio,
    .getgeo = stackbd_getgeo,
    .ioctl  = stackbd_ioctl,
};

static int __init stackbd_init(void)
{
    PINFO("is_remap=%d\n", is_remap);

    if (is_remap)
    {
        p_stackbd_io_fn = stackbd_io_fn_remap;
    }
    else
    {
        p_stackbd_io_fn = stackbd_io_fn_clone;
    }

    /* Set up our internal device */
    spin_lock_init(&stackbd.lock);

    /* Get registered */
    if ((major_num = register_blkdev(major_num, STACKBD_NAME)) < 0)
    {
        PERROR("unable to get major number\n");
        goto error_after_alloc_queue;
    }

    /* Gendisk structure */
    if (!(stackbd.gd = blk_alloc_disk(NUMA_NO_NODE)))
    {
        PERROR("unable to alloc disk\n");
        goto error_after_register_blkdev;
    }

    stackbd.gd->major = major_num;
    stackbd.gd->first_minor = 0;
    stackbd.gd->minors = 1 << 4;
    stackbd.gd->fops = &stackbd_ops;
    stackbd.gd->private_data = &stackbd;
    strcpy(stackbd.gd->disk_name, STACKBD_NAME_0);
    stackbd.queue = stackbd.gd->queue;

    if(bioset_init(&bs, 64, 0, BIOSET_NEED_BVECS) < 0)
    //if(bioset_init(&bs, BIO_POOL_SIZE, 0, 0) < 0)
    {
        PERROR( "Cannot allocate bioset");
        goto error_after_register_blkdev;
    }

    if(add_disk(stackbd.gd) < 0)
    {
        PERROR("unable to add disk\n");
        goto error_after_register_blkdev;
    }

    PINFO("init done\n");

    return 0;

error_after_register_blkdev:
    unregister_blkdev(major_num, STACKBD_NAME);
error_after_alloc_queue:
    blk_cleanup_queue(stackbd.queue);

    return -EFAULT;
}

static void __exit stackbd_exit(void)
{
    PINFO("exit\n");

    if (stackbd.is_active)
    {
        kthread_stop(stackbd.thread);
        stackbd_target_close(&stackbd.tgt);
    }

    del_gendisk(stackbd.gd);
    put_disk(stackbd.gd);
    bioset_exit(&bs);
    unregister_blkdev(major_num, STACKBD_NAME);
    blk_cleanup_queue(stackbd.queue);
}

module_init(stackbd_init);
module_exit(stackbd_exit);

https://github.com/zenbooster/stackbd/blob/5.15.0-70-generic/module/main.c

 , ,

zenbooster
()

А какие сейчас есть актуальные замены (da|ba|k|)sh для скриптов?

Форум — Development

Пишу сейчас очередной sh-скрипт с кучей вызовов awk, grep и sed. В связи с чем задумался об альтернативах. Попытался сформировать список черт, которые делают sh до сих пор актуальным инструментом:

  • Возможность легко и просто скомпилировать под любой утюг.
  • Отсутствие развесистой библиотеки, которую интерпретатор таскает с собой, а также как следствие — нет слома совместимости между версиями библиотеки.
  • Минимальное время инициализации интерпретатора.
  • Малое потребление памяти.
  • Простой параллелизм через fork.
  • Возможность удобно и просто вызывать внешние команды и пайплайны команд.
  • Возможность прозрачно миксовать внешние команды и собственные функции. (В sh мы делаем command1 | command2, и это работает одинаково, независимо от того, являются ли эти команды собственными функциями или внешними командами.)

Если обобщить, то главным отличием sh от ЯП типа perl, ruby, python и т.п. является композиция программы как совокупности исполняемых модулей, запускаемых как отдельные процессы, в противовес композиции библиотечных модулей, слинкованных в единый процесс.

Главным минусом sh является то, что в нём не развиты средства работы с какими-либо структурами данных, кроме строк. Да и для самих строк средства не развиты.

То есть потециальная альтернатива sh должна обладать всем перечнем указанных черт, но дополнительно иметь развитые средства работы со структурами данных такими как списки, хэш-массивы и т.д.

 , скриптинг

wandrien
()

Чем сжимать и разжимать картинки?

Форум — Multimedia

Есть картинки в jpg. Хотелось бы попробовать их пожать, но без потери качества.

Например, перевести в условный raw (или просто чистые данные), а потом пожать разными кодеками с целью выявления наиболее эффективного метода сжатия.

В принципе, то же относится и к видео, аудио. То бишь задача найти софт для компрессии \ декомпрессии мультимедиа. Насколько я знаю, стандартный софт в духе gzip, xz плохо сжимает уже пожатые данные (jpg, mp3, mkv). Поэтому и стало интересно: можно ли вытащить данные из таких контейнеров и сжать тем же xz или спец софтом?

Перемещено hobbit из general

 , ,

Reptile
()

whisper.cpp 1.6.0

Новости — Разработка
whisper.cpp 1.6.0
Группа Разработка

15 мая состоялся выпуск 1.6.0 высокопроизводительной системы автоматического распознавания речи whisper.cpp, реализующей модель Whisper от OpenAI на языках C и C++, и распространяемой по лицензии MIT.

Список изменений:

  • добавлена опция --flash-attn для ускорения обработки данных на устройствах с CUDA и Metal;
  • более высокая производительность на архитектуре ppc64;
  • исправлена ошибка обработки регулярного выражения в консольной утилите-примере main.

>>> Подробности

 , , , whisper,

dataman
()

Документация к языкам программирования

Форум — Development

Всевозможные учебники и книги - это хорошо, но обычно их предлагают купить и часто не совсем дёшево, даже если они описывают базовый уровень. Бесплатным решением, очевидно, является официальная документация. Когда я открыл документацию к python, я был приятно удивлён, что она написана практически как учебник. Для Java вроде бы тоже всё относительно неплохо в этом плане, хотя хотелось бы отдельный оффлайновый pdf.

Мне захотелось скачать себе документацию в подобном виде для C и C++. Зашёл на их официальные сайты, там описание стандарта предлагают получить на сайте ISO за немалые суммы денег. Да и само описание стандарта далеко не для обучения. Хорошо, подумал я, попробую тогда посмотреть документацию к одной из реализаций языка - GCC-CPP, и вижу, что описанное там тоже вовсе не подходит для обучения. Даже описания типов и примеров объявления нет (может плохо искал, но в заголовках не заметил).

Нет, это не тред «подскажите книгу по Сям», таких для начинающих я и сам могу гору насоветовать.

Вопрос следующий: существует ли нормальная доступная бесплатная документация по которой можно изучать C, C++? Официальная документация по другим языкам была бы тоже интересна.


Update

C, C++
Online-ресурсы и учебные пособия для начинающих:

Как дополнение: Рабочая версия стандарта C++14 от 19 ноября 2014 г. (с официального сайта стандарта)


Fortran


Python
В дополнение к официальной документациипереводу руководства Python 3.1):


Object Pascal. Lazarus

Перемещено Klymedy из talks

 , , , ,

grem
()

Книга c++ for real programmers

Форум — Development

Джеффа Элджера. По делитесь впечатлениями, кто читал.

 

johnson102
()

Debian несанкционированно перезагружается в 3 ночи - как выяснить причину?

Форум — Admin

Пару недель назад Debian 12 сервер стал несанкционированно перезагружаться ровно в 3 часа ночи. Первое время не каждый день, последние несколько дней - каждый день. Сначала подумал, что дело, возможно, в аппаратном сбросе, например через ИБП - но учитывая точное время перезагрузки - складывается впечатление, что перезагрузка программная.

В crontab нет никаких записей с перезагрузкой.

В логах systemd нет никакой информации указывающей на причины перезагрузки, вот пару примеров вывода journalctl соответствующего времени:

May 06 01:17:02 debi9 CRON[15085]: pam_unix(cron:session): session opened for user root(uid=0) by (uid=0)
May 06 01:17:02 debi9 CRON[15086]: (root) CMD (cd / && run-parts --report /etc/cron.hourly)
May 06 01:17:02 debi9 CRON[15085]: pam_unix(cron:session): session closed for user root
May 06 02:17:01 debi9 CRON[28717]: pam_unix(cron:session): session opened for user root(uid=0) by (uid=0)
May 06 02:17:01 debi9 CRON[28718]: (root) CMD (cd / && run-parts --report /etc/cron.hourly)
May 06 02:17:01 debi9 CRON[28717]: pam_unix(cron:session): session closed for user root
-- Boot c6a5eac4d88c464592b8a3f493fc39ff --
May 06 03:00:35 debi9 kernel: microcode: microcode updated early to revision 0x11d, date = 2023-08-29
May 06 03:00:35 debi9 kernel: Linux version 6.1.0-20-amd64 (debian-kernel@lists.debian.org) (gcc-12 (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40) #1 SMP PREEMPT_DYNAMIC Debian 6.1.85-1 (2024-04-11)
May 06 03:00:35 debi9 kernel: Command line: BOOT_IMAGE=/vmlinuz-6.1.0-20-amd64 root=UUID=320c1ce7-c162-46bc-aa90-81ecafb4ecdb ro quiet split_lock_detect=off
May 06 03:00:35 debi9 kernel: x86/tme: not enabled by BIOS
May 06 03:00:35 debi9 kernel: x86/split lock detection: disabled
May 06 03:00:35 debi9 kernel: BIOS-provided physical RAM map:
May 07 01:41:11 debi9 systemd[1]: Starting man-db.service - Daily man-db regeneration...
May 07 01:41:11 debi9 systemd[1]: man-db.service: Deactivated successfully.
May 07 01:41:11 debi9 systemd[1]: Finished man-db.service - Daily man-db regeneration.
May 07 02:17:01 debi9 CRON[295327]: pam_unix(cron:session): session opened for user root(uid=0) by (uid=0)
May 07 02:17:01 debi9 CRON[295328]: (root) CMD (cd / && run-parts --report /etc/cron.hourly)
May 07 02:17:01 debi9 CRON[295327]: pam_unix(cron:session): session closed for user root
-- Boot bd603611c06946c5a44c30660beb7bf8 --
May 07 03:00:39 debi9 kernel: microcode: microcode updated early to revision 0x11d, date = 2023-08-29
May 07 03:00:39 debi9 kernel: Linux version 6.1.0-20-amd64 (debian-kernel@lists.debian.org) (gcc-12 (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40) #1 SMP PREEMPT_DYNAMIC Debian 6.1.85-1 (2024-04-11)
May 07 03:00:39 debi9 kernel: Command line: BOOT_IMAGE=/vmlinuz-6.1.0-20-amd64 root=UUID=320c1ce7-c162-46bc-aa90-81ecafb4ecdb ro quiet split_lock_detect=off
May 07 03:00:39 debi9 kernel: x86/tme: not enabled by BIOS
May 07 03:00:39 debi9 kernel: x86/split lock detection: disabled
May 07 03:00:39 debi9 kernel: BIOS-provided physical RAM map:

Есть подозрение, что проблема как-то связана с ядром. За день до начала этих перезагрузок было проведено обновление системы с установкой ядра версии 6.1.0-18 с тех пор появились эти перезагрузки в 3 часа ночи, но не ежедневно. Несколько дней назад ядро было обновлено до 6.1.0-20 - с тех пор перезагрузки случаются каждую ночь.

Поиск обнаружил похожую тему: «PVE automatically reboots at 3 a.m. every day»: https://forum.proxmox.com/threads/pve-automatically-reboots-at-3-a-m-every-da... - симптомы очень похожи, но там нет никакого решения, тема заброшена.

Пожалуйста, подскажите, как можно выяснить конкретную причину этих перезагрузок?

(в качестве же решения пока приходит в голову только даунгрейд до предыдущей версии ядра - но это так себе решение)

 ,

Kircher
()

В какие бесплатные игры со свободными исходниками вы играете?

Форум — Games

Я в Xonotic, иногда tremulous, когда-то играл в Planeshift (тупая MMORPG игра, где нужно бегать по полупустому миру и нажимать 100 раз одни и те же кнопки в одинаковой последовательности, очень советую), nethack, warmux.

Недавно узнал про развивающийся свободный движок alephone (засилье жидомасонов!) с помощью которого можно играть в трилогию marathon от bungie, которая уже целиком стала доступна для скачивания

http://halo.bungie.net/news/content.aspx?cid=31991

Это, конечно, не систем шок, но тоже весьма интересный шутер, полный взбесившихся ИИ (которые, кстати, не всегда стремятся уничтожить всех людей на планете/корабле, как шодан) и прочих вкусностей. В общем, вполне современные, продуманные и интересные игры. Не то что щас, всякие YOBA поделия от valve

 

amphibrakhij
()

Грустная история std::optional<T&>

Форум — Talks

TLDR;

Коммитет настолько запутался в собственном языке и поленился выяснять, что к чему, что решил забанить эту конструкцию от греха подальше.

Фулл кулл стори:

Поскольку конструкция синтаксически валидная, но семантически не однозначная, решили забить на решение вопроса.

Вся драма в красках описана тут. «В красках» в прямом смысле слова - текст сопровождён картинками. Поскольку стори описана от сторонника одной из реализаций и члена коммитета С++, уровень драмы находится на надлежащем уровне.

Всем приятного чтения.

 , ,

LamerOk
()

DE на WinAPI

Форум — Development

Насколько реально сделать окружение для X на основе WinAPI для запуска под Wine, чтобы оно давало и курсор, и оконный менеджер и т.п.? Будет ли такое ПО запускаться под Windows?

 , ,

gedisdone
()

Очередь сообщений с ожиданием нового сообщения в ядре по типу select()

Форум — Development

Пишу приложение, в котором обмен сообщениями между несколькими потоками я собираюсь организовать при помощи очередей сообщений. При чем каждый поток должен ожидать сообщения от нескольких потоков одновременно. То есть, алгоритм ожидания событий должен быть полностью идентичен алгоритму ожидания событий в select(). Сами очереди событий буду писать сам, объектами SysV пользоваться не буду, так как мне не нужно взаимодействие между процессами. Проблема в том, что все алгоритмы, реализации которых мне удалось найти предлагают различные варианты с периодическим опросом и ожиданием, типа sleep(). Но в них присутствует задержка на обработку событий и бессмысленное периодическое просыпание потоков для проверки. Есть ли вариант реализации без этих дефектов? Прошу помощи с информацией.

 ,

leonopulos
()

Ещё один Форт

Форум — Development

Здравствуйте, коллеги!

Любите ли вы язык Форт так же, как полюбил его я? До недавнего времени его не любил. Уважал - да, но любви не было. Как к какому-то забытому старичку из прошлого к нему относился. Лабораторные когда-то в древности на Форте делал. Сделал и забыл. Но так произошло, что в недавнем времени пришлось нудно и долго писать на ассемблере. Иногда такое бывает, тогда и вспомнился язык Форт. И чем больше вспоминаю узнаю Forth, тем он мне кажется интересней и интересней. И кажется незаслуженно забытым.

В общем, ежели вдруг кто захочет освежить память или ознакомиться с языком Форт, то загляните сюда - https://github.com/L4OS/yaforth

Если понравилось - дайте как-нибудь знать. Найдёте ошибку - вдвойне дайте знать.

Если кто желает покритиковать код, стиль, алгогитмы, поучить программировать/жить - то почему бы и не в этой теме, но в пределах правил.

Спасибо за внимание, ведь именно его так не хватает.

 

alman
()

Накидайте книг для продвинутого Си под онтопик

Форум — Development

Сто лет назад прочитал K&R и всегда хватало, а если я хочу углУбить?

// друг спрашивает :)

UPD: собрал из темы списочек, особо не редактируя (экстримов и модернов поболее одного, но пусть будет) – думаю, заглянувшим в будущем будет полезно:

  • modern c by jens gustedt
  • Thomas Mailund - Pointers in C Programming (2021)
  • Gustedt - Modern C (2020)
  • Kalin - Modern C Up and Running (2022)
  • King - C Programming. A Modern Approach, 2nd ed. (2008)
  • Хэзфилд «Искусство программировани на C»
  • «Язык C в XXI веке»
  • Экстремальный Си
  • extreme c programming
  • «UNIX. Профессиональное программирование» Уильям Ричард Стивенс, Стивен А. Раго
  • C Interfaces and Implementations: Techniques for Creating Reusable Software
  • Peter van der Linden, Expert C Programming: Deep C Secrets https://progforperf.github.io/Expert_C_Programming.pdf
  • Чан Теренс «Системное программирование на С++ для Unix»

 ,

pihter
()

Разработка сетевой библиотеки на C++20: интеграция асинхронности и алгоритма Raft (часть 2)

Статьи — Разработка
Разработка сетевой библиотеки на C++20: интеграция асинхронности и алгоритма Raft (часть 2)

Эта статья является продолжением предыдущей публикации, в которой описывается разработка сетевой библиотеки на C++20. В данном продолжении акцент сделан на более детальном описании разработки алгоритма Raft и его интеграции с сетевой библиотекой.

( читать дальше... )

 , , ,

Reset
()

Разработка сетевой библиотеки на C++20: интеграция асинхронности и алгоритма Raft (часть 1)

Статьи — Разработка
Разработка сетевой библиотеки на C++20: интеграция асинхронности и алгоритма Raft (часть 1)

Введение

С годами работы в области распределённых систем, я понял, что мой опыт не будет полным без реализации алгоритма Raft. Это осознание побудило меня к действию: я решил создать свою реализацию, используя асинхронные возможности C++20.

( читать дальше... )

 , , , ,

Reset
()

Обработка сканированных документов

Форум — Multimedia

Занимаюсь сейчас следующим делом.

Есть несколько сотен изображений со сканами чертежей. Их нужно обработать таким образом:

  1. На большинстве сканов лист лежит под небольшим углом. Нужно довернуть изображение на этот угол, чтобы выровнять картинку.
  2. Некоторые листы сканировались в несколько приёмов. Например, лист формата A3x4 сканирован в 5 приёмов с перекрытиями. Нужно из таких фрагментов собрать одно цельное изображение.
  3. Результаты нужно собрать в PDF.

Гуглю автоматически средства, которыми можно решить задачи 1 и 2.

Для первой нашел скрипт на питоне, который детектит прямые линии на листе. Планирую использовать его - доработать, чтобы автоматически определять угол поворота листа.

Для второй нашел еще один скрипт на питоне, который детектит общие опорные точки для склейки панорамы и по ним формирует изображение. Проверил - работает неплохо, но очень долго.

Дайте знать, если есть какие-то готовые решения, которые не требуют пилинг кода на питоне и баше. Я что-то не смог нагуглить.

 , ,

wandrien
()

SObjectizer-5.8.0 и so5extra-1.6.0

Форум — Development

Вышли очередные версии библиотек SObjectizer и so5extra.

Полный список изменений можно найти в Wiki:

https://github.com/Stiffstream/sobjectizer/wiki/v.5.8.0

https://github.com/Stiffstream/so5extra/wiki/v.1.6.0

Менее полный, но с большим погружением в отдельные моменты, обзор изменений сделан в свежей статье на Хабре.

Если же говорить в двух словах, то начата новая ветка 5.8, в которой пришлось пойти на слом совместимости с предыдущей веткой 5.7. Так что при переходе на SO-5.8 потребуется модифицировать исходники. Не получилось придумать способ внедрить новую функциональность не поломав совместимость :(

Для тех, кто не знает меня и не слышал про этот проект, вкратце:

SObjectizer – это один из «акторных фреймворков» для C++ (еще есть QP/C++, CAF: C++ Actor Framework и rotor). Краткий обзор SObjectizer-а можно найти в этой презентации или в этой статье. Кроме модели акторов SObjectizer поддерживает еще и такие модели как Publish-Subscribe и Communicating Sequential Processes. А so5extra – это набор дополнительных полезных прибамбасов для SObjectizer-а, которые не хотелось добавлять в сам SObjectizer.

В двух словах, SObjectizer, – это инструмент для упрощения разработки некоторых типов многопоточных приложений на C++.

Новая версия уже доступна через vcpkg, добавление в conan пока задерживается, но надеюсь, что скоро она появится и там.


Готов к тому, что в меня будут бросаться гнилыми помидорами за рекламу образцового нинужно, но как можно было обойтись без поста на LOR-е, по старой доброй традиции? ;)

 , , , ,

eao197
()

Вопросы по баги BIOS int13h и GRUB2

Форум — General

Написал такие вопросы в рассылку GRUB2, если кто из олдов помнит баги BIOS’ов и как всё это должно работать корректно — расскажите, пожалуйста. По моему мнению получается, что баги во всех трёх компонентах: BIOS, GRUB, gdisk/установщик debian.

Hello list,

I noticed that GRUB 2.06 menu and Linux kernel and initrd load times are greatly influenced by the "last sector" data in the first partition entry (byte 0x06 in MBR partition entry, offset 0x1c4 from the beginning of the disk for the first partition) on my WYSE C10LE x86 thin client (32-bit VIA Eden Esther with Phoenix bios, from 2008).

Fresh Debian 12 installation takes about 5 seconds to show GRUB menu (GRUB loading... for 5 seconds), the kernel (4.5 MB) is loaded in 27 seconds, and initrd takes ages to load.

However, if I use gdisk software to perform MBR→GPT→MBR partition table type conversion, without touching any partitions per se, GRUB speeds up by an order of magnitude: the menu is shown instantly and the kernel is loaded under 3 seconds, initrd takes about 8 seconds.

Several hours of debugging resulted in the following observations:

1. My BIOS returns some strange C/H/S values in int13h, influenced by "last sector" data in the first partition entry of MBR. With stock Debian MBR it's 301/255/2, with MBR→GPT→MBR it's 480/255/63.

Debian's MBR contain 4/4/1 CHS start, 255/254/194 CHS end.
Converted MBR contain 1/0/1 CHS start, 255/254/255 CHS end.

Is this a BIOS bug, or some kind of quirk? I don't see this behavior on SeaBIOS in qemu. Does Debian installer fill MBR correctly? Does gdisk fill it correctly?

2. Slow loading times are due to low sector value with stock MBR. GRUB is forced to read only 2 sectors at a time.

3. GRUB obeys CHS layout even if LBA via IBM/MS INT13 Extensions is used. My BIOS supports INT13 extensions and the reads are performed using it, but GRUB still reads by 2 sectors.

grub-core/disk/i386/pc/biosdisk.c, function grub_biosdisk_open contains the following logic for HDD:

if (grub_biosdisk_get_diskinfo_standard() != 0) /* if it fails */ {
  if (data->flags & GRUB_BIOSDISK_FLAG_LBA) {
    data->sectors = 63;
    data->heads = 255;
    ...
  }
}

That means it rewrites the value for LBA only if CHS function fails. Shouldn't LBA mode ignore CHS values and read as many as possible? Is this a GRUB bug? I've changed the function to always rewrite data for LBA to 64 (not 63) sectors, to fill the whole segment in a single read, and it seem to work fine. With 63 sectors GRUB reads 63 sectors, then 1 sector, then 63 sectors, then 1 sector again, which decreases the performance, but not by much.


P.S. nativedisk doesn't have any performance problems.
Thanks.

 , ,

ValdikSS
()

Как сделать профиль A2DP доступным?

Форум — Linux-hardware

Обновил дебьян с 11 до 12, кеды такие красивые сразу, и тут такое на вентилятор, подключаю bluetooth наушники JBL TUNE500BT а они играют котофонию, хотя до этого на качество звука я не жаловался никогда. Проблема очевидно в профиле воспроизведения, точнее в том что считает A2DP недоступным. Хочется нормально музыку слушать.

Важая вырезка с команды pacmd list-cards:

...
profiles:
                a2dp_sink: Воспроизведение высокого качества (приёмник A2DP) (priority 40, available: no)
                handsfree_head_unit: Гарнитура (HFP) (priority 30, available: yes)
                off: Выключено (priority 0, available: yes)
        active profile: <handsfree_head_unit>
...

В общем все возможные гуи мне об этом и говорят, pipewire кстати тоже не смог подцепить A2DP.

Полный вывод:

$ pacmd list-cards 
2 card(s) available.
    index: 0
        name: <alsa_card.pci-0000_00_1f.3>
        driver: <module-alsa-card.c>
        owner module: 6
        properties:
                alsa.card = "0"
                alsa.card_name = "HDA Intel PCH"
                alsa.long_card_name = "HDA Intel PCH at 0xf1320000 irq 138"
                alsa.driver_name = "snd_hda_intel"
                device.bus_path = "pci-0000:00:1f.3"
                sysfs.path = "/devices/pci0000:00/0000:00:1f.3/sound/card0"
                device.bus = "pci"
                device.vendor.id = "8086"
                device.vendor.name = "Intel Corporation"
                device.product.id = "9d71"
                device.product.name = "Sunrise Point-LP HD Audio"
                device.form_factor = "internal"
                device.string = "0"
                device.description = "Встроенное аудио"
                module-udev-detect.discovered = "1"
                device.icon_name = "audio-card-pci"
        profiles:
                input:analog-stereo: Аналоговый стерео вход (priority 32833, available: unknown)
                output:analog-stereo: Аналоговый стерео выход (priority 39268, available: unknown)
                output:analog-stereo+input:analog-stereo: Аналоговый стерео дуплекс (priority 39333, available: unknown)
                output:hdmi-stereo: Digital Stereo (HDMI) выход (priority 38668, available: unknown)
                output:hdmi-stereo+input:analog-stereo: Digital Stereo (HDMI) выход + Аналоговый стерео вход (priority 38733, available: unknown)
                output:hdmi-stereo-extra1: Digital Stereo (HDMI 2) выход (priority 5700, available: no)
                output:hdmi-stereo-extra1+input:analog-stereo: Digital Stereo (HDMI 2) выход + Аналоговый стерео вход (priority 5765, available: unknown)
                output:hdmi-surround-extra1: Digital Surround 5.1 (HDMI 2) выход (priority 600, available: no)
                output:hdmi-surround-extra1+input:analog-stereo: Digital Surround 5.1 (HDMI 2) выход + Аналоговый стерео вход (priority 665, available: unknown)
                output:hdmi-surround71-extra1: Digital Surround 7.1 (HDMI 2) выход (priority 600, available: no)
                output:hdmi-surround71-extra1+input:analog-stereo: Digital Surround 7.1 (HDMI 2) выход + Аналоговый стерео вход (priority 665, available: unknown)
                output:hdmi-stereo-extra2: Digital Stereo (HDMI 3) выход (priority 5700, available: no)
                output:hdmi-stereo-extra2+input:analog-stereo: Digital Stereo (HDMI 3) выход + Аналоговый стерео вход (priority 5765, available: unknown)
                output:hdmi-surround-extra2: Digital Surround 5.1 (HDMI 3) выход (priority 600, available: no)
                output:hdmi-surround-extra2+input:analog-stereo: Digital Surround 5.1 (HDMI 3) выход + Аналоговый стерео вход (priority 665, available: unknown)
                output:hdmi-surround71-extra2: Digital Surround 7.1 (HDMI 3) выход (priority 600, available: no)
                output:hdmi-surround71-extra2+input:analog-stereo: Digital Surround 7.1 (HDMI 3) выход + Аналоговый стерео вход (priority 665, available: unknown)
                off: Выключено (priority 0, available: unknown)
        active profile: <output:analog-stereo+input:analog-stereo>
        sinks:
                alsa_output.pci-0000_00_1f.3.analog-stereo/#0: Встроенное аудио Аналоговый стерео
        sources:
                alsa_output.pci-0000_00_1f.3.analog-stereo.monitor/#0: Monitor of Встроенное аудио Аналоговый стерео
                alsa_input.pci-0000_00_1f.3.analog-stereo/#1: Встроенное аудио Аналоговый стерео
        ports:
                analog-input-internal-mic: Internal Microphone (priority 8900, latency offset 0 usec, available: unknown)
                        properties:
                                device.icon_name = "audio-input-microphone"
                analog-input-mic: Microphone (priority 8700, latency offset 0 usec, available: no)
                        properties:
                                device.icon_name = "audio-input-microphone"
                analog-output-speaker: Speakers (priority 10000, latency offset 0 usec, available: unknown)
                        properties:
                                device.icon_name = "audio-speakers"
                analog-output-headphones: Headphones (priority 9900, latency offset 0 usec, available: no)
                        properties:
                                device.icon_name = "audio-headphones"
                hdmi-output-0: HDMI / DisplayPort (priority 5900, latency offset 0 usec, available: yes)
                        properties:
                                device.icon_name = "video-display"
                                device.product.name = "G27QC A"
                hdmi-output-1: HDMI / DisplayPort 2 (priority 5800, latency offset 0 usec, available: no)
                        properties:
                                device.icon_name = "video-display"
                hdmi-output-2: HDMI / DisplayPort 3 (priority 5700, latency offset 0 usec, available: no)
                        properties:
                                device.icon_name = "video-display"
    index: 3
        name: <bluez_card.E8_D0_3C_7A_6B_E0>
        driver: <module-bluez5-device.c>
        owner module: 23
        properties:
                device.description = "JBL TUNE500BT"
                device.string = "E8:D0:3C:7A:6B:E0"
                device.api = "bluez"
                device.class = "sound"
                device.bus = "bluetooth"
                device.form_factor = "headset"
                bluez.path = "/org/bluez/hci0/dev_E8_D0_3C_7A_6B_E0"
                bluez.class = "0x240404"
                bluez.alias = "JBL TUNE500BT"
                bluetooth.battery = "90%"
                device.icon_name = "audio-headset-bluetooth"
                device.intended_roles = "phone"
                bluetooth.codec = "mSBC"
        profiles:
                a2dp_sink: Воспроизведение высокого качества (приёмник A2DP) (priority 40, available: no)
                handsfree_head_unit: Гарнитура (HFP) (priority 30, available: yes)
                off: Выключено (priority 0, available: yes)
        active profile: <handsfree_head_unit>
        sinks:
                bluez_sink.E8_D0_3C_7A_6B_E0.handsfree_head_unit/#5: JBL TUNE500BT
        sources:
                bluez_sink.E8_D0_3C_7A_6B_E0.handsfree_head_unit.monitor/#10: Monitor of JBL TUNE500BT
                bluez_source.E8_D0_3C_7A_6B_E0.handsfree_head_unit/#11: JBL TUNE500BT
        ports:
                headset-output: Гарнитура (priority 0, latency offset 0 usec, available: yes)
                        properties:

                headset-input: Гарнитура (priority 0, latency offset 0 usec, available: yes)
                        properties:



Думается мне что копать надо в настройки самого блютуза.


Пофиксил конфиги

  1. /etc/bluetooth/main.conf

В [General]

Name = BlueZ
Disable=headset
  1. /etc/pulse/default.pa

Раскомментировать load-module module-alsa-sink и добавить load-module module-switch-on-connect

Потом ребут

Теперь всё работает

Создателям дебиан шлю привет за божественную настройку A2DP

 , , , ,

nikitalol
()

Списки игр

Форум — Games

Ищу списки свободных игр под GNU/Linux. Пока нашёл только это: https://www.allegro.cc/ http://osgameclones.com/

 ,

misteralter
()