Chinaunix首页 | 论坛 | 博客
  • 博客访问: 98592
  • 博文数量: 6
  • 博客积分: 157
  • 博客等级: 民兵
  • 技术积分: 102
  • 用 户 组: 普通用户
  • 注册时间: 2012-12-25 14:18
文章分类

全部博文(6)

文章存档

2013年(1)

2012年(5)

分类: LINUX

2012-12-25 14:39:48

linux共享库实现互斥

概述

Sqlite3数据库互斥是基于文件的,即一个数据库文件中如果包含多张表T1、T2...Tn,当有进程对其中的表Tx进行写操作时,其余试图读写Tn的操作都会立即返回IS_LOCK,导致写数据库失败。因此,Sqlite3经常用于嵌入式开发中对并发要求不高的场景。

悲剧的是现有的系统用的是Sqlite3,但却要求较高的并发度。

于是一个选择被提上议程:更换数据库 or 修改现有sqlite3的行为?

长远来看,更换数据库方为解决之道,但目前来说修改现有sqlite3的行为投入较少,先解燃眉之急。

 

修订方案

将sqlite3_exec函数修订为阻塞和非阻塞两种方式。

 

技术选择

Sqlite3作为数据库,以文件的形式存在,供多进程访问,实现数据共享。操作Sqlite3的接口被编译成共享库的形式供多进程动态链接调用。要对sqlite3_exec函数实现互斥,必然需要新增互斥变量,不管使用信号量还是锁,都会遇到一个问题:互斥变量使用共享库的形式发布,各进程调用的时候会在自己的内存空间拷贝一个副本,导致各个进程无法实现互斥。解决这个问题有多种方法,这边记录有名信号量的使用。

 

实验程序


 

点击(此处)折叠或打开

  1. share.c:

  2. #include "share.h"

  3. sem_t *sem = NULL;

  4. void print_num()
  5. {
  6.    int tmp;
  7.     sem = sem_open("my_sem", O_RDWR);
  8.     if (sem == NULL) {
  9.      printf("Get sem failed.\n");
  10.      return ;
  11.     }
  12.     
  13.     printf("Open sem success.\n");
  14.     
  15.     sem_wait(sem);
  16.    printf("Input the number, 0 for quit\n");
  17.    while(1) {
  18.     scanf("%d", &tmp);
  19.     printf("The input is %d.\n", tmp);
  20.     if (0 == tmp) {
  21.      printf("Input 0, ending...\n");
  22.      sem_post(sem);
  23.      return ;
  24.     }
  25.     printf("================================================\n");
  26.    }
  27. }


  28. void share_init()
  29. {
  30.     /* 创建一个命名信号量 */
  31.     sem = sem_open("my_sem", O_RDWR|O_CREAT, 0077, 1);
  32.     if (sem == NULL) {
  33.      printf("Create sem failed.\n");
  34.      return ;
  35.     }
  36.     printf("Create sem success.\n");
  37. }

 

点击(此处)折叠或打开

  1. share.h:

  2. #include <semaphore.h>
  3. #include <stdio.h>
  4. #include <errno.h>
  5. #include <fcntl.h>

  6. extern void print_num();
  7. extern void share_init();

以上两个文件被编译成共享库:share.c:gcc -fPIC -shared -pthread -o share.so share.c

点击(此处)折叠或打开

  1. share_init.c:

  2. #include "share.h"

  3. void main()
  4. {
  5.  share_init();
  6.  printf("Init OK.\n");
  7. }

以上文件被编译成share_init程序,用于初始化信号量:share_init.c:gcc -o share_init share_init.c ./share.so

点击(此处)折叠或打开

  1. test.c:

  2. #include "share.h"

  3. void main()
  4. {
  5.  sem_t *sem_tmp = NULL;
  6.  sem_tmp = sem_open("my_sem", O_RDWR, 0077, 1);
  7.   if (sem_tmp == NULL) {
  8.     printf("Get sem failed.\n");
  9.     return ;
  10.   }
  11.  print_num();

  12. }

以上文件被编译成test程序,用于访问共享库中的互斥资源:test.c:gcc -o test test.c ./share.so

将test程序拷贝为test1和test2,运行两个中断T1、T2,在T1中执行share_init,运行test1,在T2中运行test2,结果可以发现在test1未释放信号量之前,test2会被挂起,在test1程序正常退出后,test2就可以得到运行,以此实现了共享库的互斥。

 

结论

以上重点是该信号量被声明为有名信号量,如果是无名信号量则无法实现共享库的互斥。

阅读(3249) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~