Linux openssl堆栈详解

编程语言 12/11 阅读 690 views次 人气 0
摘要:

一 openssl堆栈

堆栈是一种先进后出的数据结构。openssl大量采用堆栈来存放数据。
它实现了一个通用的堆栈,可以方便的存储任意数据。
它实现了许多基本的堆栈操作,主要有:堆栈拷贝(sk_dup)、构建新堆栈(sk_new_null,sk_new)、插入数据(sk_insert)、删除数据(sk_delete)、查找数据(sk_find,sk_find_ex)、入栈(sk_push)、出栈(sk_pop)、获取堆栈元素个数(sk_num)、获取堆栈值(sk_value)、设置堆栈值(sk_set)和堆栈排序(sk_sort)。
 
二 openssl堆栈数据结构
openssl堆栈数据结构在stack.h中定义如下:
  1. typedefstruct stack_st
  2. {
  3. int num;
  4. char**data;
  5. int sorted;
  6. int num_alloc;
  7. int(*comp)(constchar*const*,constchar*const*);
  8. }STACK;
各字段意义如下:
num:堆栈中存放数据的个数。
data:用于存放数据地址,每个数据地址存放在data[0]到data[num-1]中。
sorted:堆栈是否已排序,如果排序则值为1,否则为0,堆栈数据一般是无序的,只有当用户调用了sk_sort操作,其值才为1。
comp:堆栈内存放数据的比较函数地址,此函数用于排序和查找操作;当用户生成一个新堆栈时,可以指定comp为用户实现的一个比较函数;或当堆栈已经存在时通过调用sk_set_cmp_func函数来重新指定比较函数。
注意,用户不需要调用底层的堆栈函数(sk_sort、sk_set_cmp_func等),而是调用他通过宏实现的各个函数。
 
三 openssl堆栈源码
openssl堆栈实现源码位于crypto/stack目录下。下面分析了部分函数。
1、sk_set_cmp_func
此函数用于设置堆栈存放数据的比较函数。由于堆栈不知道用户存放的是什么数据,所以,比较函数必须由用户自己实现。
2、sk_find
根据数据地址来查找它在堆栈中的位置。当堆栈设置了比较函数时,它首先对堆栈进行排序,然后通过二分法进行查找。如果堆栈没有设置比较函数,它只是简单的比较数据地址来查找.
3、sk_sort
本函数对堆栈数据排序。它首先根据sorted来判断是否已经排序,如果未排序则调用了标准C函数qsort进行快速排序。
4、sk_pop_free
本函数用于释放堆栈内存放的数据以及堆栈本身,它需要一个由用户指定的针对具体数据的释放函数。如果用户仅调用sk_free函数,则只会释放堆栈本身所用的内存,而不会释放数据内存。
 
四 定义用户自己的堆栈函数
用户直接调用最底层的堆栈操作函数是一个麻烦的事情,对此openssl提供了用宏来帮助用户实现接口。用户可以参考safestack.h来定义自己的上层堆栈操作函数,举例如下,safestack.h定义了如下关于GENERAL_NAME数据结构的堆栈操作:
  1. #define sk_GENERAL_NAME_new(st) SKM_sk_new(GENERAL_NAME,(st))
  2. #define sk_GENERAL_NAME_new_null() SKM_sk_new_null(GENERAL_NAME)
  3. #define sk_GENERAL_NAME_free(st) SKM_sk_free(GENERAL_NAME,(st))
  4. #define sk_GENERAL_NAME_num(st) SKM_sk_num(GENERAL_NAME,(st))
  5. #define sk_GENERAL_NAME_value(st, i) SKM_sk_value(GENERAL_NAME,(st),(i))
  6. #define sk_GENERAL_NAME_set(st, i, val) SKM_sk_set(GENERAL_NAME,(st),(i),(val))
  7. #define sk_GENERAL_NAME_zero(st) SKM_sk_zero(GENERAL_NAME,(st))
  8. #define sk_GENERAL_NAME_push(st, val) SKM_sk_push(GENERAL_NAME,(st),(val))
  9. #define sk_GENERAL_NAME_unshift(st, val) SKM_sk_unshift(GENERAL_NAME,(st),(val))
  10. #define sk_GENERAL_NAME_find(st, val) SKM_sk_find(GENERAL_NAME,(st),(val))
  11. #define sk_GENERAL_NAME_find_ex(st, val) SKM_sk_find_ex(GENERAL_NAME,(st),(val))
  12. #define sk_GENERAL_NAME_delete(st, i) SKM_sk_delete(GENERAL_NAME,(st),(i))
  13. #define sk_GENERAL_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_NAME,(st),(ptr))
  14. #define sk_GENERAL_NAME_insert(st, val, i) SKM_sk_insert(GENERAL_NAME,(st),(val),(i))
  15. #define sk_GENERAL_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_NAME,(st),(cmp))
  16. #define sk_GENERAL_NAME_dup(st) SKM_sk_dup(GENERAL_NAME, st)
  17. #define sk_GENERAL_NAME_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_NAME,(st),(free_func))
  18. #define sk_GENERAL_NAME_shift(st) SKM_sk_shift(GENERAL_NAME,(st))
  19. #define sk_GENERAL_NAME_pop(st) SKM_sk_pop(GENERAL_NAME,(st))
  20. #define sk_GENERAL_NAME_sort(st) SKM_sk_sort(GENERAL_NAME,(st))
  21. #define sk_GENERAL_NAME_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAME,(st))
当用户想对GENERAL_NAME数据进行堆栈操作时,调用上面由宏定义的函数即可,即直观又方便。比如用户想设置堆栈数据的比较函数和对堆栈排序时,可分别调用:sk_GENERAL_NAME_set_cmp_func和sk_GENERAL_NAME_sort。
 
五 openssl堆栈编程实例
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<openssl/safestack.h>
  5. #define sk_Student_new(st) SKM_sk_new(Student,(st))
  6. #define sk_Student_new_null() SKM_sk_new_null(Student)
  7. #define sk_Student_free(st) SKM_sk_free(Student,(st))
  8. #define sk_Student_num(st) SKM_sk_num(Student,(st))
  9. #define sk_Student_value(st, i) SKM_sk_value(Student,(st),(i))
  10. #define sk_Student_set(st, i, val) SKM_sk_set(Student,(st),(i),(val))
  11. #define sk_Student_zero(st) SKM_sk_zero(Student,(st))
  12. #define sk_Student_push(st, val) SKM_sk_push(Student,(st),(val))
  13. #define sk_Student_unshift(st, val) SKM_sk_unshift(Student,(st),(val))
  14. #define sk_Student_find(st, val) SKM_sk_find(Student,(st),(val))
  15. #define sk_Student_delete(st, i) SKM_sk_delete(Student,(st),(i))
  16. #define sk_Student_delete_ptr(st, ptr) SKM_sk_delete_ptr(Student,(st),(ptr))
  17. #define sk_Student_insert(st, val, i) SKM_sk_insert(Student,(st),(val),(i))
  18. #define sk_Student_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(Student,(st),(cmp))
  19. #define sk_Student_dup(st) SKM_sk_dup(Student, st)
  20. #define sk_Student_pop_free(st, free_func) SKM_sk_pop_free(Student,(st),(free_func))
  21. #define sk_Student_shift(st) SKM_sk_shift(Student,(st))
  22. #define sk_Student_pop(st) SKM_sk_pop(Student,(st))
  23. #define sk_Student_sort(st) SKM_sk_sort(Student,(st))
  24. typedefstructStudent_st
  25. {
  26. char*name;
  27. int age;
  28. char*otherInfo;
  29. }Student;
  30. typedef STACK_OF(Student)Students;
  31. Student*Student_Malloc()
  32. {
  33. Student*a=malloc(sizeof(Student));
  34. a->name=(char*)malloc(sizeof(char)*20);
  35. strcpy(a->name,"zcp");
  36. a->otherInfo=(char*)malloc(sizeof(char)*20);
  37. strcpy(a->otherInfo,"no info");
  38. return a;
  39. }
  40. voidStudent_Free(Student*a)
  41. {
  42. free(a->name);
  43. free(a->otherInfo);
  44. free(a);
  45. }
  46. int main()
  47. {
  48. Students*s;
  49. Student*s1,*one;
  50. int i,num;
  51. s=sk_Student_new_null();/* 新建一个堆栈对象 */
  52. s1=Student_Malloc();
  53. sk_Student_push(s,s1);
  54. num=sk_Student_num(s);
  55. for(i=0; i<num; i++)
  56. {
  57. one=sk_Student_value(s,i);
  58. printf("student name : %s\n",one->name);
  59. printf("sutdent age : %d\n",one->age);
  60. printf("student otherinfo : %s\n\n\n",one->otherInfo);
  61. }
  62. sk_Student_pop_free(s,Student_Free);
  63. return0;
  64. }
运行结果
  1. [root@localhost ~]# cd /
  2. [root@localhost /]# cd /openssl-1.1.0c/test
  3. [root@localhost test]# gcc example1.c -o example1 -L/usr/lib -lssl -lcrypto
  4. [root@localhost test]#./example1
  5. student name : zcp
  6. sutdent age :1934268344
  7. student otherinfo : no info
 

评论

该文章不支持评论!

分享到: