快速,持续,稳定,傻瓜式
支持Mysql,Sqlserver数据同步

[apue] apue_db:一个可以充当注册表的 key-value 数据库

在线QQ客服:1922638

专业的SQL Server、MySQL数据库同步软件

后面的两章将通过一个完整的示例来说明一些Linux功能。第20章将解释通过数据库实例使用文件锁,

坦白地说,当时我并不感兴趣,因为整个页面上都充满了源代码和解析,所以我不愿意看它。但是,当我拿起它并顽固地查看它时,我发现这是一个小型演示,显然它是一个完整的键值数据库,

而且,该数据库提供多进程并发读写安全保证(通过文件锁定),回收已删除节点的能力以及根据用户需求调整内部哈希表参数的能力。 \ hellip;

特别是它的索引和数据文件格式,使用字符串来存储各种偏移量和数字,直接打开文件进行一些”观察”非常方便,然后根据它来建立搜索也非常方便。 SDK,用于添加,删除和修改数据库的工具\ hellip;

这只是Linux上的”注册表”工具!

首先查看此数据库提供的SDK接口:

apue_db.h

  1  #ifndef __APUE_DB_H__

2 #define __APUE_DB_H__

3

4 typedef void * DBHANDLE;

5

6 // db_store标志

7 #define DB_INSERT 1

8 #define DB_REPLACE 2

9 #define DB_STORE 3

10

11 #define IDXLEN_MIN 6

12 #define IDXLEN_MAX 1024 // 单个索引不能超过此大小

13 #define DATLEN_MIN 2

14 #define DATLEN_MAX 1024 // 单个数据不能超过此大小

15 #define NHASH_DEF 137 // 默认哈希表大小

16

17 DBHANDLE db_open( char const *路径名, int oflag,... );

18 void db_close(DBHANDLE db);

19 int db_store(DBHANDLE db, const char * key, const char *数据, int 标志);

20 char * db_fetch(DBHANDLE db, char * 键);

21 int db_delete(DBHANDLE db, const char * 键);

22 void db_rewind(DBHANDLE db);

23 char * db_nextrec(DBHANDLE db, char * 键);

24 void db_dump(DBHANDLE db);

25

26 #endif

通过db_open/db_close打开和关闭数据库。获得DBHANDLE之后,您可以根据以下内容进行操作:

  • db_store存储密钥,并且标志指定覆盖方法:

    • 该密钥已经存在时,DB_INSERT将失败
    • 没有这样的密钥时,DB_REPLACE将失败
    • DB_STORE结合了以上两种情况,有时是替换,有时是插入
  • db_fetch获取与键对应的数据
  • db_delete删除密钥
  • db_rewind/db_nextrec用于不按顺序遍历数据库中的所有键
  • db_dump是我添加的自己的接口,用于打印数据库的内部状态,例如在调试期间使用的索引哈希表,无索引的节点列表

实现时间相对较长,因此我不会发布它,只需给出一个链接:apu_db.c

根据书中的代码,手工输入,并在练习中添加指定索引哈希表大小的功能

(HAS_HASHSIZE宏是在编译时指定的,并且特定的哈希值是在运行时通过APUE_DB_HASH_SIZE环境变量指定的。当然,这仅在创建数据库时有效。如果数据库已经存在,则

数据库中记录的哈希表大小值将直接使用。如果没有环境变量,请使用NHASH_DEF作为默认哈希表大小。 PS:尽可能使用质数以确保散列效果)

使用SDK,数据库小工具简直是小菜一碟:

db.c

  1  #include "   https://www.cnblogs.com/goodcitizen/apue.h  " 

2 #include " apue_db。h "

3 #include \ lt; fcntl.h \ gt;

4 #include \ lt; strings.h \ gt;

5 #include \ lt; errno.h \ gt;

6

7 void 用法()

8

9 printf(" 用法:db filename插入关键数据\\\\ n " );

10 printf(" db文件名查询键\\\\ n " );

11 printf(" db文件名删除键\\\\ n " );

12 printf(" db filename walk \\\\ n " );

13 printf(" db filename dump \\\\ n " );

14 出口(- 1 );

15 }

16

17 int main( int argc, char * argv [])

18

19 如果(argc \ lt; 3

20 用法();

21

22 char * filename = argv [ 1 ];

23 char * action = argv [ 2 ];

24 char *键= NULL;

25 char * data = NULL;

26 if (strcasecmp(action," 步行 " )== 0

27 || strcasecmp(操作," dump " )== 0

28

29 // 没有多余的参数

30 }

31 其他 if (strcasecmp(action," 删除 " )== 0

32 || strcasecmp(操作," 查询 " )== 0

33

34 如果(argc \ lt; 4

35 用法();

36

37 键= argv [ 3 ];

38 }

39 其他 if (strcasecmp(action," 插入 " )== 0

40

41 如果(argc \ lt; 5

42 用法();

43

44 键= argv [ 3 ];

45 data = argv [ 4 ];

46 }

47 else

48 {

49 用法();

50 }

51

52 DBHANDLE db;

53 char * ptr = NULL;

54 #ifdef HAS_HASHSIZE

55 int hashsize = 0 ;

56 ptr = getenv(" APUE_DB_HASH_SIZE "

57 如果 (ptr)

58 hashsize = atoi(ptr);

59

60 如果(哈希大小\ lt; = 0

61 hashsize = NHASH_DEF;

62

63 如果((db = db_open(filename,O_RDWR | O_CREAT ,FILE_MODE,hashsize))== NULL)

64 #else

65 如果((db = db_open(filename,O_RDWR | O_CREAT ,FILE_MODE))== NULL)

66 #endif

67 err_sys(" db_open错误 " );

68

69 int ret = 0 ;

70 如果(strcasecmp(action," dump " )== 0

71 {

72 db_dump(db);

73 }

74 其他 if (strcasecmp(action," 步行 " )== 0

75

76 // db_rewind();

77 int n = 0 ;

78 char buf [IDXLEN_MAX] = {< 0 };

79 while ((ptr = db_nextrec(db,buf))! = NULL)

80

81 n ++ ;

82 printf(" [%5d]%s---%s \\\\ n " , n,buf,ptr);

83 }

84

85 printf(" 行走完成!\\\\ n " );

86 }

87 其他 if (strcasecmp(action," 插入 " )== 0

88

89 ret = db_store(数据库,键,数据,DB_STORE);

90 if (ret \ lt; 0

91 fprintf(stderr," 插入%s。%S失败,错误号%d \\\\ n " ,键,数据,错误号);

92 else 如果(ret == 1

93 fprintf(stderr," 插入%s。%S覆盖旧数据\\\\ n " ,键,数据);

94 else

95 printf(" db% s"%s"代码%d \\\\ n " ,动作,键,ret );

96 }

97 其他 if (strcasecmp(action," 删除 " )== 0

98

99 ret = db_delete(db,键);

100 if (ret \ lt; 0

101 fprintf(stderr," delete%s失败,errno%d \\\\ n " ,key ,errno);

102 else

103 printf(" db% s"%s" code%d \\\\ n " ,动作,键,ret );

104 }

105 其他 if (strcasecmp(action," 查询 " )== 0

106

107 ptr = db_fetch(db,键);

108 // printf("%s ===%s \\\\ n",键,ptr);

109 // 仅打印允许在shell脚本中分配的数据

110 printf(" %s \\\\ n " ,ptr == NULL?" nil " :ptr);

111 }

112 else

113 用法();

114

115 db_close(db);

116 return 退

117 }

如果给定的参数不合法,将弹出用法:

用法:db filename插入密钥数据

db文件名查询键

db文件名删除键

数据库文件名遍历

数据库文件名转储

其中:

  • 插入的底层使用db_store(…,DB_STORE);插入一条数据
  • 查询的底层使用db_fetch查询一条数据
  • 删除的最底层使用db_delete删除一条数据
  • 遍历底部使用db_nextrec遍历所有数据
  • 转储的底部使用db_dump来检查数据库的内部状态

好的,有了这个工具,我们可以使用脚本来执行测试工作。为了验证该数据库是否”可靠”,我的主要测试是并行写入和删除多个进程的能力。

在开始做事之前,我需要准备一些测试数据。这是通过awk脚本完成的:

gen.awk

  1 #!/bin/ awk - f

2 BEGIN {

3 WORDNUM = 10

4 for (i = 1 ; i \ lt; = WORDNUM; i ++ ){

5 printf(" %s%s \\\\ n " ,randword(randint( 20 )),randword(randint( 150 )))

6 }

7 }

8

9 #randint(n):返回一个随机整数其中是\ gt; = 1 和\ lt; = n

10 函数 randint(n){

11 return int (n * rand())+ 1

12 }

13

14 #randlet():返回随机字母,其中 可能是大写,小写或数字。

15 函数 randlet(){

16 return substr(" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 " ,randint( 62 ), 1

17 }

18

19 #randword(LEN):返回长度为LEN的rand单词

20 函数 randword(LEN){

21 randw = ""

22 for (j = 1 ; j \ lt; = LEN; j ++ ){

23 randw = randw randlet()

24 }

25 返回randw

26 }

执行此脚本以获取测试数据文件:

 $ https://www.cnblogs.com/goodcitizen/p/gen.awk \ gt;演示

$猫演示

s0jKl kEjwE4q3nNJugFJ0cgNaSgDpP3VS45x3Wum9kRF6SgmIReFmrNBcCecjyQHQqCrB5fC61hao1BV2x6XZ6KLtA4jZTEnhcAugAMMWE95NU7FnsYar4

TmD516yvmt JB2NG30NDAaL5vpzp8DQX0rLRiVxjONIm64AN6UVc7uTLIIRpEq

BOhc40pKXhCbCu8 yo1vVWWxtP4uJIbRFwNo6eZnxbOnzwrRvrcX0Xi1DcKsHcsaCgoqkbr1PWoqSdcG5jbwi4sMrlGf

Pw1o1fcg6kHIm ZmDlGY0OEsAsWYzRprJJcjxOZ0h9OBP5ORTqmvxU2XgS9lRXAfCuIzFHOLVt1eE

GalRFwb YpHtiHoEVu46gDh6X55JbQMr9T9mI5PIwCllwe1sy1lUkQn2EqJAE9tZ0bTpMNj7nVenVaEpJEBHai

2X staN43MMZxs8H3wITgkcuTKWGRxLE8pYpUTc2SUETv9igtejxiiM2B6x44ch9XGZjkXSMp2Rewv2WjRBHSVfZAmTAYz32h5l5PRKsdHqMMU1l

zW4dQI 6tnikssfMBLVJs4jbTXkFylvdEcVGMB1eYpdCvnvqBxcuuMPmDgSDuFVl726MkkgzMU5nFLoQrcM4Y8aTHRnMXilQTEaMe5aYdgJ5jEVnKMwRt9mQ

0Jde UQQFJQpluZKXybyfzyLrdIGYNn8Rs09tXwv7uMjlYRpe7C1frEB5hGHwuEu37bSCj0v5L1cxnYLabzF4t4loXtiV97O7XXg4qMK5IR2

yNSPh9ev0rnu0yU I3XVWF8h7to0

UivjVVXnSN60cre Grro31PCJDUx83CjbThVEksrvQHZcxnLwBa3RCpUS0Yhwm4OXisdZN0Jnj

此文件的每一行都是一个”密钥数据”,其中key是一个长度为1-20的随机字符串,而data是一个长度为1-150的随机字符串,总共为10。/p>

用于写数据的测试脚本可以这样写:

testi.sh

  1 #!/bin/ sh 

2 OLD_IFS = " $ IFS "

3 IFS = " "

4 while 读取行

5

6 echo $ line

7 array = ($行)

8 键= $ {array [ 0 ]}

9 data = $ {array [ 1 ]}

10 echo " $ key-\ gt; $ data "

11 https://www.cnblogs.com/goodcitizen/p/ db yunh插入$ key $ data

12 完成 \ lt; 演示

13

14 IFS = " $ OLD_IFS "

执行此脚本,结果如下:

 $ https://www.cnblogs.com/goodcitizen/p/testi.sh

s0jKl-> kEjwE4q3nNJugFJ0cgNaSgDpP3VS45x3Wum9kRF6SgmIReFmrNBcCecjyQHQqCrB5fC61hao1BV2x6XZ6KLtA4jZTEnhcAugAMMWE95NU7Fns

db插入" s0jKl"代码0

TmD516yvmt-> JB2NG30NDAaL5vpzp8DQX0rLRiVxjONIm64AN6UVc7uTLIIRpEq

db插入" TmD516yvmt"代码0

BOhc40pKXhCbCu8-> yo1vVWxtP4uJIbRFwNo6eZnxbOnzwrRvrcX0Xi1DcKsHcsaCgoqkbr1PWoqSdcG5jbwi4sMrlGf

db插入" BOhc40pKXhCbCu8"代码0

Pw1o1fcg6kHIm-> ZmDlGY0OEsAsWYzRprJJcjxOZ0h9OBP5ORTqmvxU2XgS9lRXAfCuIzFHOLVt1eE

db插入" Pw1o1fcg6kHIm"代码0

GalRFwb-> YpHtiHoEVu46gDh6X55JbQMr9T9mI5PIwCllwe1sy1lUkQn2EqJAE9tZ0bTpMNj7nVenVaEpJEBHai

db插入" GalRFwb"代码0

2X-> staN43MMZxs8H3wITgkcuTKWGRxLE8pYpUTc2SUETv9igtejxiiM2B6x44ch9XGZjkXSMp2Rewv2WjRBHSVfZAmTAYz32h5l5PRKsdHqMMU1l

db插入" 2X"代码0

zW4dQI-> 6tnikssfMBLVJs4jbTXkFylvdEcVGMB1eYpdCvnvqBxcUuMPmDgSDuFVl726MkkgzMU5nFLoQrcM4Y8aTHRnMXilQTEaMe5aYdgJ5jVnVJTJDJJV

db插入" zW4dQI"代码0

0Jde-> UQQFJQpluZKXybyfzyLrdIGYNn8Rs09tXwv7uMjlYRpe7C1frEB5hGHwuEu37bSCj0v5L1cxnYLabzF4t4loXtiV97O7XXg4qMK5IR2

db插入" 0Jde"代码0

yNSPh9ev0rnu0yU-> I3XVWF8h7to0

db插入" yNSPh9ev0rnu0yU"代码0

UivjVVXnSN60cre-> Grro31PCJDUx83CjbThVEksrvQHZcxnLwBa3RCpUS0Yhwm4OXisdZN0Jnj

db插入" UivjVVXnSN60cre"代码0

如果使用工具行走,则可以看到它们都已插入:

 $ https://www.cnblogs.com/goodcitizen/p/db yunh walk

[1] s0jKl---kEjwE4q3nNJugFJ0cgNaSgDpP3VS45x3Wum9kRF6SgmIReFmrNBcCecjyQHQqCrB5fC61hao1BV2x6XZ6KLtA4jZTEnhcAugAMMWE95NU7

[2] TmD516yvmt---JB2NG30NDAaL5vpzp8DQX0rLRiVxjONIm64AN6UVc7uTLIIRpEq

[3] BOhc40pKXhCbCu8---yo1vVWxtP4uJIbRFwNo6eZnxbOnzwrRvrcX0Xi1DcKsHcsaCgoqkbr1PWoqSdcG5jbwi4sMrlGf

[4] Pw1o1fcg6kHIm---ZmDlGY0OEsAsWYzRprJJcjxOZ0h9OBP5ORTqmvxU2XgS9lRXAfCuIzFHOLVt1eE

[5] GalRFwb-YpHtiHoEVu46gDh6X55JbQMr9T9mI5PIwCllwe1sy1lUkQn2EqJAE9tZ0bTpMNj7nVenVaEpJEBHai

[6] 2X---staN43MMZxs8H3wITgkcuTKWGRxLE8pYpUTc2SUETv9igtejxiiM2B6x44ch9XGZjkXSMp2Rewv2WjRBHSVfZAmTAYz32h5l5PRKsdHqMMU1l

[7] zW4dQI-6tnikssfMBLVJs4jbTXkFylvdEcVGMB1eYpdCvnvqBxcUuMPmDgSDuFVl726MkkgzMU5nFLoQrcM4Y8aTHRnMXilQTEaMe5aYdgJ5jEVnKMwt9

[8] 0Jde---UQQFJQpluZKXybyfzyLrdIGYNn8Rs09tXwv7uMjlYRpe7C1frEB5hGHwuEu37bSCj0v5L1cxnYLabzF4t4loXtiV97O7XXg4qMK5IR2

[9] yNSPh9ev0rnu0yU---I3XVWF8h7to0

[10] UivjVVXnSN60cre---Grro31PCJDUx83CjbThVEksrvQHZcxnLwBa3RCpUS0Yhwm4OXisdZN0Jnj

走完!

可以看出,遍历的顺序实际上是元素的插入顺序。

如果使用该工具进行转储,还可以在哈希表中看到元素的分配:

 $ https://www.cnblogs.com/goodcitizen/p/db yunh dump

哈希节点:

哈希[0]个节点:

哈希[1]个节点:

哈希[2]个节点:

哈希[3]个节点:

哈希[4]个节点:

哈希[5]个节点:

哈希[6]个节点:

哈希[7]个节点:

哈希[8]个节点:

哈希[9]个节点:

哈希[10]个节点:

哈希[11]节点:

哈希[12]个节点:

哈希[13]个节点:

1键10,日期52:TmD516yvmt

哈希[14]个节点:

哈希[15]个节点:

哈希[16]个节点:

哈希[17]个节点:

哈希[18]个节点:

哈希[19]个节点:

哈希[20]个节点:

哈希[21]个节点:

哈希[22]个节点:

哈希[23]个节点:

哈希[24]个节点:

哈希[25]个节点:

哈希[26]个节点:

哈希[27]个节点:

哈希[28]个节点:

哈希[29]节点:

散列[30]个节点:

哈希[31]个节点:

哈希[32]个节点:

散列[33]个节点:

哈希[34]个节点:

哈希[35]个节点:

哈希[36]个节点:

哈希[37]节点:

哈希[38]个节点:

哈希[39]个节点:

哈希[40]个节点:

哈希[41]节点:

1键15,数据13:yNSPh9ev0rnu0yU

哈希[42]个节点:

哈希[43]节点:

哈希[44]节点:

哈希[45]个节点:

哈希[46]个节点:

哈希[47]节点:

哈希[48]个节点:

哈希[49]节点:

哈希[50]个节点:

哈希[51]个节点:

1键6,dat 151:zW4dQI

哈希[52]节点:

哈希[53]节点:

哈希[54]节点:

哈希[55]个节点:

哈希[56]个节点:

哈希[57]节点:

哈希[58]节点:

哈希[59]节点:

哈希[60]个节点:

哈希[61]个节点:

1键15,数据59:UivjVVXnSN60cre

哈希[62]个节点:

哈希[63]节点:

哈希[64]个节点:

1键7,dat 79:GalRFwb

哈希[65]个节点:

哈希[66]节点:

哈希[67]个节点:

哈希[68]节点:

哈希[69]节点:

哈希[70]个节点:

哈希[71]个节点:

哈希[72]个节点:

哈希[73]个节点:

哈希[74]节点:

哈希[75]个节点:

哈希[76]个节点:

哈希[77]个节点:

哈希[78]个节点:

1键4,数据104:0Jde

哈希[79]节点:

哈希[80]个节点:

哈希[81]节点:

哈希[82]节点:

哈希[83]节点:

哈希[84]节点:

哈希[85]节点:

哈希[86]节点:

哈希[87]个节点:

哈希[88]节点:

哈希[89]个节点:

1键2,dat 110:2X

哈希[90]个节点:

哈希[91]节点:

哈希[92]节点:

哈希[93]节点:

哈希[94]节点:

1键15,数据76:BOhc40pKXhCbCu8

哈希[95]节点:

哈希[96]节点:

哈希[97]节点:

哈希[98]点头es:

哈希[99]节点:

哈希[100]个节点:

哈希[101]节点:

哈希[102]节点:

哈希[103]节点:

哈希[104]节点:

哈希[105]节点:

哈希[106]节点:

哈希[107]个节点:

哈希[108]个节点:

哈希[109]节点:

散列[110]节点:

哈希[111]节点:

哈希[112]个节点:

散列[113]个节点:

哈希[114]节点:

哈希[115]节点:

1键13,数据64:Pw1o1fcg6kHIm

哈希[116]个节点:

哈希[117]节点:

哈希[118]节点:

哈希[119]个节点:

散列[120]个节点:

哈希[121]节点:

哈希[122]节点:

哈希[123]个节点:

哈希[124]节点:

哈希[125]个节点:

哈希[126]个节点:

哈希[127]个节点:

哈希[128]个节点:

哈希[129]个节点:

哈希[130]节点:

哈希[131]节点:

哈希[132]个节点:

哈希[133]个节点:

哈希[134]节点:

哈希[135]个节点:

哈希[136]个节点:

1键5,数据123:s0jKl

空闲节点:

总免费:0

您可以看到默认的137个哈希槽足以哈希这10条记录,因此基本上一个哈希槽最多只有一个记录。如果有很多记录,则可以在哈希槽的队列中看到索引记录。情况。

另外,因为没有记录的删除,也没有插入具有相同名称的键的情况(这种情况下也会删除记录),所以freelist没有任何元素。

如果您有兴趣,实际上可以打开数据库索引和数据文件以查找:

 $ cat yunh.idx

0 137 0 0 0 0 0 0 0 0 0 0 0 0 0 0 857
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1043 0 0 0 0 0
0 0 0 0 995 0 0 0 0 0 0 0 0 1076 0
0 949 0 0 0 0 0 0 0 0 0 0 0 0 1020
0 0 0 0 0 0 0 0 0 974 0 0 0 0 0 885
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 918 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 835

0 12s0jKl:0:123

0 18TmD516yvmt:123:52

0 23BOhc40pKXhCbCu8:175:76

0 21Pw1o1fcg6kHIm:251:64

0 15GalRFwb:315:79

0 112X:394:110

0 15zW4dQI:504:151

0 130Jde:655:104

0 23yNSPh9ev0rnu0yU:759:13

0 23UivjVVXnSN60cre:772:59

$ cat yunh.dat

kEjwE4q3nNJugFJ0cgNaSgDpP3VS45x3Wum9kRF6SgmIReFmrNBcCecjyQHQqCrB5fC61hao1BV2x6XZ6KLtA4jZTEnhcAugAMMWE95NU7FnsYar4wz279jHoV

JB2NG30NDAaL5vpzp8DQX0rLRiVxjONIm64AN6UVc7uTLIIRpEq

yo1vVWxtP4uJIbRFwNo6eZnxbOnzwrRvrcX0Xi1DcKsHcsaCgoqkbr1PWoqSdcG5jbwi4sMrlGf

ZmDlGY0OEsAsWYzRprJJcjxOZ0h9OBP5ORTqmvxU2XgS9lRXAfCuIzFHOLVt1eE

YpHtiHoEVu46gDh6X55JbQMr9T9mI5PIwCllwe1sy1lUkQn2EqJAE9tZ0bTpMNj7nVenVaEpJEBHai

staN43MMZxs8H3wITgkcuTKWGRxLE8pYpUTc2SUETv9igtejxiiM2B6x44ch9XGZjkXSMp2Rewv2WjRBHSVfZAmTAYz32h5l5PRKsdHqMMU1l

6tnikssfMBLVJs4jbTXkFylvdEcVGMB1eYpdCvnvqBxcUuMPmDgSDuFVl726MkkgzMU5nFLoQrcM4Y8aTHRnMXilQTEaMe5aYdgJ5jEVnKMwRt9mQHS8WYK

UQQFJQpluZKXybyfzyLrdIGYNn8Rs09tXwv7uMjlYRpe7C1frEB5hGHwuEu37bSCj0v5L1cxnYLabzF4t4loXtiV97O7XXg4qMK5IR2

I3XVWF8h7to0

Grro31PCJDUx83CjbThVEksrvQHZcxnLwBa3RCpUS0Yhwm4OXisdZN0Jnj

我在这里不赘述,但总体感觉是该数据库相对”透明”。

同时执行多个进程,此数据当然是不够的,我们修改gen.awk,使其生成1000个数据,

然后运行后台进程以在脚本调用db命令的同时运行多个进程:

 https://www.cnblogs.com/goodcitizen/p/db yunh insert $ key $ data  \  

执行此操作后,再次查看数据库中的数据。通过执行漫游或转储,您可以看到确实插入了1,000个数据。

为了验证数据的准确性,我什至编写了一个验证脚本。该脚本一次从测试数据中读取一行密钥和数据,然后转到数据库以获取数据进行比较,

经过验证,还不错!

如果您有兴趣,可以参考以下脚本:

testq.sh

  1 #!/bin/ sh 

2 OLD_IFS = " $ IFS "

3 IFS = " "

4 n = 0

5 while 读取行

6

7 echo $ line

8 array = ($行)

9 键= $ {array [ 0 ]}

10 data = $ {array [ 1 ]}

11 resp =`https://www.cnblogs.com/goodcitizen/p/ db yunh query $ key $ data`

12 如果 [" $ resp " ! = " $ data " ]; 然后

13 echo " 使用$ resp!= $数据查询$键 "

14 n = $(($ n + 1 ))

15 fi

16 完成 \ lt; 演示

17 echo " 总计不同:$ n "

18

19 IFS = " $ OLD_IFS "

20

最近致力于将Windows移植到linux程序上,注册表访问的这一部分令人头疼,因为编写配置文件确实是零散的,并且不能保证并发性问题,

因此,我自然想到将这个SDK封装在用于访问配置信息的跨平台类中,该类用于模拟在Windows上访问注册表的机制。

(这只是一件事,因为底层文件锁仅支持进程级互斥。如果同一进程中的多个线程之间已经存在锁,则会添加该锁,而不会等待。它进入关键部分。

因此,这一部分仍然需要注意,访问”注册表”最好仅限于进程的一个线程,尤其是在存在写入场景时)

最后,总而言之,apue本身就是一个大宝库。看似简单的演示包含巨大的潜力。作者值得成为一代大师。

相关推荐

咨询软件
 
QQ在线咨询
售前咨询热线
QQ1922638