linux内核模块数据压缩

时间:2018-03-03 13:41:33

标签: linux kernel compression

linux 2.6 我正在写一个LKM。我需要动态地压缩和解压缩许多不同的文本块。

我更喜欢调用内核api,避免包含和编译外部库。

是否有内核Api来压缩和解压缩内存? 源和目标缓冲区既可以在内核内存中,也可以在内核中,另一个在用户空间中。

1 个答案:

答案 0 :(得分:0)

不确定为什么kernel.org排除压缩部分。

一个人可能需要模仿其官方的skcipher示例,其过程如下所示:

tfm = crypto_alloc_tfm("yourAlg",
                       CRYPTO_TFM_MODE_yourAlg);
req = skcipher_request_alloc(tfm, GFP_KERNEL);
skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                  test_tfm_cb,
                  result);
crypto_cipher_setkey(tfm, key, keylength);
crypto_cipher_encrypt(tfm, &scatterlist,
                      numlists);
tfm_request_free(req);
crypto_free_tfm(tfm);

通知内核现在正在移至异步,但是最新的header文件中未显示回调。

/**
 * acomp_request_set_callback() -- Sets an asynchronous callback
 *
 * Callback will be called when an asynchronous operation on a given
 * request is finished.
 *
 * @req:        request that the callback will be set for
 * @flgs:       specify for instance if the operation may backlog
 * @cmlp:       callback which will be called
 * @data:       private data used by the caller
 */
static inline void acomp_request_set_callback(struct acomp_req *req,
                                              u32 flgs,
                                              crypto_completion_t cmpl,
                                              void *data)
{
        req->base.complete = cmpl;
        req->base.data = data;
        req->base.flags = flgs;
}

示例代码:

    struct comp_testvec tv, int mode;
    int ilen = tv.inlen;    
    char *str_input = tv.input;
    int olen = tv.outlen;
    char *str_output = tv.output;

    struct scatterlist sg[2];
    struct scatterlist sg2[2];
    char *input;
    char *output;
    char *input2;
    char *output2;
    struct acomp_req *req;
    struct crypto_acomp *tfm;
    struct tcrypt_result result;
    int ret = 0;

    input = kmalloc(ilen, GFP_KERNEL);
    output = kmalloc(olen, GFP_KERNEL);
    input2 = kmalloc(olen, GFP_KERNEL);
    output2 = kmalloc(ilen, GFP_KERNEL);


    char *driver = tv.alg;
    tfm = crypto_alloc_acomp(driver, CRYPTO_ALG_TYPE_ACOMPRESS,
                   CRYPTO_ALG_TYPE_ACOMPRESS_MASK);
    if (IS_ERR(tfm)) {
        printk(KERN_ERR "alg: acomp: Failed to load transform for "
               "%s: %ld\n", driver, PTR_ERR(tfm));
        return PTR_ERR(tfm);
    }

    init_completion(&result.completion);


if (mode == 0)
{
    //zip
    memcpy(input,str_input,ilen);
    printk("input => %s\n", input);    
    print_hex_dump(KERN_CONT, "| ", DUMP_PREFIX_OFFSET, 16, 1, input, ilen, false);

    printk("alg => %s\n",driver);

    sg_init_one(&sg[0], input, ilen);
    sg_init_one(&sg[1], output, COMP_BUF_SIZE);

    req = acomp_request_alloc(tfm);
    if(!req)
    {
        printk("error req = null\n");
        crypto_free_acomp(tfm);
        return -1;  
    }
    acomp_request_set_params(req, &sg[0], &sg[1], ilen, COMP_BUF_SIZE);
    acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                       tcrypt_complete, &result);

    ret = crypto_acomp_compress(req);

    if(ret == -EINPROGRESS || ret == -EBUSY)
    {
        ret = wait_for_completion_interruptible(
            &result.completion);
        if (!ret && !((ret = result.err)))
        {
            reinit_completion(&result.completion);
        }
    }
    else if(ret  == 0)
    {
        printk("succ\n");
    }
    else
    {
        printk("error ret = %d\n",ret);
        goto out;
    }
    printk("compress => \n");
    print_hex_dump(KERN_CONT, "| ", DUMP_PREFIX_OFFSET, 16, 1, output, olen, false);

} else if (mode == 1) {
//unzip
    memcpy(input2,str_output,olen);
    printk("input => \n");    
    print_hex_dump(KERN_CONT, "| ", DUMP_PREFIX_OFFSET, 16, 1, input2, olen, false);

    char *driver = tv.alg;
    printk("alg => %s\n",driver);

      //sg init
    sg_init_one(&sg2[0], input2, ilen);
    sg_init_one(&sg2[1], output2, COMP_BUF_SIZE);

    req = acomp_request_alloc(tfm);
    if(!req)
    {
        printk("error req = null\n");
        crypto_free_acomp(tfm);
        return -1;  
    }
    acomp_request_set_params(req, &sg2[0], &sg2[1], ilen, COMP_BUF_SIZE);
    acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                       tcrypt_complete, &result);

    ret = crypto_acomp_decompress(req);

    if(ret == -EINPROGRESS || ret == -EBUSY)
    {
        ret = wait_for_completion_interruptible(
            &result.completion);
        if (!ret && !((ret = result.err)))
        {
            reinit_completion(&result.completion);
        }
    }
    else if(ret  == 0)
    {
        printk("succ\n");
    }
    else
    {
        printk("error ret = %d\n",ret);
        goto out;
    }
    printk("decompress => %s\n", output2);
    print_hex_dump(KERN_CONT, "| ", DUMP_PREFIX_OFFSET, 16, 1, output2, ilen, false);