免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3621 | 回复: 8

一个测试sys_read, sys_write原子性的程序 [复制链接]

论坛徽章:
0
发表于 2010-10-27 12:16 |显示全部楼层
编译:
gcc  -lpthread  test.c
运行:
./a.out  4 1      //4个线程写,暂停1us,不用fsync
./a.out 4  1 1   //用fsync


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <pthread.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>

  10. #define LEN 3*4000

  11. int fd;
  12. int need_sync = 0;
  13. int sync_done = 0;

  14. void run(void *arg)
  15. {
  16.     char buf[LEN];
  17.     int usecs = *((int *)arg);
  18.     int n, i = 0;

  19.     i = pthread_self()%255;
  20.     memset(buf, i%31+'A', sizeof(buf));
  21.     printf("%lu === %c\n", pthread_self(), i%31+'A');
  22.     while(1)
  23.     {
  24.         sync_done = 0;
  25.         lseek(fd, 0, 0);
  26.         n = write(fd, buf, sizeof(buf));
  27.         if(n != sizeof(buf)) printf("ERROR! ******* partial write ******\n");
  28.         if(need_sync) fsync(fd);
  29.         sync_done = 1;
  30.         //fprintf(stdout, "%d:%08x:%d\n", i++, (int )pthread_self(), usecs);
  31.         usleep(usecs);
  32.     }
  33. }

  34. void see()
  35. {
  36. int nbad = 0;
  37. char buf[LEN];
  38. int r, n;

  39.     r = 0;
  40.     while(1) {

  41.         while(sync_done == 0);
  42.         lseek(fd, 0, 0);
  43.         n = read(fd, buf, sizeof(buf));
  44.         sync_done = 0;
  45.         r++;
  46.         if(r % 1024 == 0) printf("%d %d\n", r, n);

  47.         if(buf[0] != buf[sizeof(buf)-8]) {
  48.                 printf("BAD DATA: %c --- %c\n", buf[0], buf[sizeof(buf)-8]);
  49.         }
  50.         //sleep(1);
  51.     }
  52. }

  53. int main(int argc, char **argv)
  54. {
  55.     int threads_num = 0;
  56.     int sleep_usecs = 0;
  57.     int i = 0;
  58.     pthread_t thread_id = 0;

  59.     if(argc < 3)
  60.     {
  61.         fprintf(stderr, "Usage:%s threads_num sleep_usec(s)\n", argv[0]);
  62.         _exit(-1);
  63.     }

  64.     if(argv[3]) need_sync = 1;


  65.     fd = open("./1111", O_CREAT | O_RDWR);
  66.     printf("fd = %d\n", fd);


  67.     threads_num = atoi(argv[1]);
  68.     sleep_usecs = atoi(argv[2]);
  69.     for(i = 0; i < threads_num; i++)
  70.     {
  71.         if(pthread_create(&thread_id, NULL, (void *)&run, (void *)&sleep_usecs) == 0)
  72.         {
  73.             fprintf(stdout, "created thread[%d][%08x] sleep_usecs:%d\n",
  74.                     i, (int )thread_id, sleep_usecs);
  75.         }
  76.     }
  77.     pthread_create(&thread_id, NULL, (void *)&see, (void *)&sleep_usecs);
  78.     while(1)
  79.     {
  80.         usleep(sleep_usecs);
  81.     }
  82.     return 0;
  83. }


复制代码

论坛徽章:
0
发表于 2010-10-27 12:18 |显示全部楼层
1)看程序有什么问题(包括错误)没有。
2)分析结果看。

论坛徽章:
0
发表于 2010-10-30 14:10 |显示全部楼层
回复 1# 思一克


    可否将测试结果描述下.我没有环境
另外在open的时候加APPEND参数结果又是什么?

论坛徽章:
0
发表于 2010-10-30 15:46 |显示全部楼层
回复 3# epegasus


结果是,不用fsync(./a.out 4 1)
结果是大量的乱的。
用了fsync(./a.out 4 1 1)
基本不乱了。前面有几个乱的,后面跑一天也不出一个。
估计是我的程序考虑不周到造成的。

APPEND方式下不乱。这个不用测试,也不容易测试,因为块大了文件一会将磁盘就充满了。
我的应用程序几十上百进程同时APPEND写LOG, 10年了也没有乱过的。写的块大小不定,但都小于4096.

论坛徽章:
0
发表于 2010-10-30 16:17 |显示全部楼层
本帖最后由 epegasus 于 2010-10-30 16:19 编辑

回复 4# 思一克


      提个建议.如果要测试同步的话放在 open选项中
当see里面的n 不完全的时候也建议打印出来.
另外如果是测试多个write之间的交错问题.应该排除write和read的交错带来的影响
所以可以设计一个读写锁.不过这个锁恰好反用.多个写可以并发获得锁.读独占锁

论坛徽章:
0
发表于 2010-10-30 16:30 |显示全部楼层
回复 5# epegasus


write之间不交错的。不是有那个i_mutex互斥吗。
乱的原因是读和write之间没有互斥。完全可以在写了一半的时候被读到了,结果自然是乱的了。

论坛徽章:
0
发表于 2010-10-30 17:17 |显示全部楼层
本帖最后由 epegasus 于 2010-10-30 17:24 编辑

回复 6# 思一克


    其实pipe里也互斥.但仍然交错. 因为pipe里会在适当的时间释放.我在那个帖子里说明了.本来是一对lock unlock但是在适当的时候中间插入unlock lock
普通文件目前还没有发现哪里有释放。但是2.6中那个for可能导致在一个 write里数据不完全的写入.这个不确定.因为那个返回EIOCBRETRY的机制还没完全弄清楚.另一个帖子里提到了这点.

论坛徽章:
0
发表于 2010-10-30 18:19 |显示全部楼层
回复 7# epegasus


  你说的对。
PIPE写中间可以释放锁头。所以也会交错。但每次写的大小小于PIPE_BUF即可保证原子性。

论坛徽章:
2
戌狗
日期:2013-11-06 17:35:36寅虎
日期:2014-10-20 23:12:29
发表于 2010-10-30 19:04 |显示全部楼层
来学习学习
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

PostgreSQL中国大会,早鸟票抢购!

PostgreSQL中国大会,早鸟票抢购!
2019年11月29~11月30日,由 PostgreSQL中文社区与ITPUB联合主办的第九届《PostgreSQL 中国技术大会》将在北京隆重召开。PostgreSQL 作为功能最强的的开源关系型数据库之一,得到了越来越多企业的推广和运用,也越来越受到广大技术爱好者的欢迎和重视。这将是 PostgreSQL 的又一次交流盛会。




----------------------------------------

点击报名>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP