linux 2.6 我正在写一个LKM。我需要动态地压缩和解压缩许多不同的文本块。
我更喜欢调用内核api,避免包含和编译外部库。
是否有内核Api来压缩和解压缩内存? 源和目标缓冲区既可以在内核内存中,也可以在内核中,另一个在用户空间中。
答案 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);