linux数据管理,【Linux】 数据管理

内存管理

从segmentation fault (core dumped)问题出发:

原因(目前我遇到的):

一个是内存访问越界;

一个是访问空指针。

malloc calloc realloc的区别:

void *malloc(size_t size)

void *calloc(size_t number_of_elements, size_t element_size);

void *realloc(void *existing_memory, size_t new_size);

malloc 和 calloc都是返回一段空间的首地址, 里面的值都被初始化为0;

realloc一般是对calloc和malloc内存进行扩充,一般(如果可以)将会在原来的地址后续添加,否则将在新地址上新辟空间,将原地址的数据拷贝过去。

一般的使用如下:

my_ptr = malloc(BLOCK_SIZE);

...

tmp_ptr = my_ptr;

tmp_ptr = realloc(tmp_ptr, BLOCK_SIZE*2);

if (tmp_ptr != NULL) {

my_ptr = tmp_ptr;

}

这里考虑的地方有俩处:

1)realloc 可能返回 NULL

2)realloc成功的话,会自动判断realloc返回的指针是否跟先前的一致,不一致会自动free掉(来自 realloc函数心得 )

文件锁定

创建文件锁:

文件锁的原理,就是创建文件(建立锁),如果文件已存在(已经有进程创建文件锁) 则返回错误信息。

文件锁的创建, 是通过系统调用open(“lock_file”,O_RDWR|O_CREAT|O_EXCL, 0444)创建的。其中,O_CREAT|O_EXCL 表示如果文件未存在则创建,否则返回错误信息(17),open失败(返回-1).其中0444,表示创建文件的权限rwx(这里应该是-r–r–r–)

这里是例子程序:

#include

#include

#include

#include

#include

const char *lock_file = "/tmp/LCK.test2";

int main()

{

int file_desc;

int tries = 10;

while(tries --) {

file_desc = open(lock_file, O_RDWR|O_CREAT| O_EXCL, 0444);

if (file_desc == -1) {

printf("%d - Lock already present\n", getpid());

printf("Open failed with error %d\n", errno);

sleep(3);

} else {

//这里是临界区

//***********************

printf("%d - I have exclusive access\n", getpid());

sleep(1);

//***********************

(void)close(file_desc);

//此处"删除"文件, 理解为释放锁

(void)unlink(lock_file);

sleep(2);

}

}

exit(EXIT_SUCCESS);

}

其中 unlink 的作用是“删除“文件, 这里准确的来说 是删除(硬)链接。linux删除一个文件,是看其硬链接个数, 如果硬链接个数为0, 则该文件被标记为可覆盖(其实文件内容仍然存在,直至新的文件写入覆盖之,毕竟真正的删除是很费事的(每个字节全部替换成0xcc?))

区域锁定

概要:锁定一个文件的某个区域

方式有fcntl(最常用) lockf。注意 由于俩者使用不同的底层实现,所以必须坚决的使用其中一种

函数调用为int fcntl(int fildes, int command, struct flock *flock_structure);

flock 结构包括:

1)short l_type

2)short l_whence

3)off_t l_start

4)off_t l_len

5)pid_t l_pid

其中l_type取值有F_RDLCK, F_WRLCK, F_UNLCK. 分别为共享锁,独占锁,解锁。(read允许有多个(共享),write只能有一个(独占),并且read时不允许有writer,write时不允许有reader。读者-写者问题)

//读者-写者问题代码

//writer

do{

wait(writeLock);

...

//write here

...

signal(writeLock);

} while(TRUE);

//reader

do {

wait(readLock);

readcount++;

if (readcount == 1)

wait(writeLock);

signal(readLock);

...

//read here

...

wait(readLock);

readcount--;

if (readcount == 0)

signal(writeLock);

signal(readLock);

} while(TRUE);

其中readLock是保证readcount多线程的安全,而总的来看,reader也是 wait(writeLock) ... signal(writeLock).

回到fcntl(fildes, command, flock_structure)

其中command 有 F_GETLK F_SETLK F_SETLKW.

F_GETLK:

尝试获取锁的信息,一般会返回不为-1的值,而且一般会修改flock_structure,l_pid此时的值是当前获得锁的进程id号,此处flock需要使用的值是type,whence,start,len,pid

F_SETLK:

功能为加锁,如果加锁失败(如对已独占区域加锁,对共享区域加独占锁)函数返回-1.(l_pid 与get不同 此时并不会修改)

F_SETLKW:

功能与上文一致,不同的是,无法得到锁时,将等待。。。只有在获得锁或者接受到信号才返回。

这三种锁,将会随着相关文件描述符fildes的关闭而自动清除。

代码:

//来自 Linux程序设计

lock3.c

#include

#include

#include

#include

const char *test_file = "/tmp/test_lock";

int main()

{

int file_desc;

int byte_count;

char *byte_to_write = "A";

struct flock region_1;

struct flock region_2;

int res;

file_desc = open(test_file, O_RDWR | O_CREAT, 0666);

if (!file_desc) {

fprintf(stderr, "Unable to open %s for read/write\n", test_file);

exit(EXIT_FAILURE);

}

for (byte_count = 0; byte_count < 100; byte_count++) {

(void)write(file_desc, byte_to_write, 1);

}

region_1.l_type = F_RDLCK;

region_1.l_whence = SEEK_SET;

region_1.l_start = 10;

region_1.l_len = 20;

region_2.l_type = F_WRLCK;

region_2.l_whence = SEEK_SET;

region_2.l_start = 40;

region_2.l_len = 10;

//it is ok.

//region_2.l_start = 10;

//region_2.l_len = 20;

printf("Process %d locking file\n", getpid());

res = fcntl(file_desc, F_SETLK, &region_1);

if (res == -1) fprintf(stderr, "Failed to lock region 1\n");

res = fcntl(file_desc, F_SETLK, &region_2);

if (res == -1) fprintf(stderr, "Failed to lock region 2\n");

sleep(60);

printf("Process %d closing file\n", getpid());

close(file_desc);

exit(EXIT_SUCCESS);

}

lock4.c

#include

#include

#include

#include

const char *test_file = "/tmp/test_lock";

#define SIZE_TO_TRY 5

void show_lock_info(struct flock *to_show);

int main()

{

int file_desc;

int res;

struct flock region_to_test;

int start_byte;

file_desc = open(test_file, O_RDWR | O_CREAT, 0666);

if (!file_desc) {

fprintf(stderr, "Unable to open %s for read/write", test_file);

exit(EXIT_FAILURE);

}

for (start_byte = 0; start_byte < 99; start_byte += SIZE_TO_TRY) {

region_to_test.l_type = F_WRLCK;

region_to_test.l_whence = SEEK_SET;

region_to_test.l_start = start_byte;

region_to_test.l_len = SIZE_TO_TRY;

region_to_test.l_pid = -1;

printf("Testing F_WRLCK on region from %d to %d\n",

start_byte, start_byte+SIZE_TO_TRY);

res= fcntl(file_desc, F_GETLK, &region_to_test);

if (res == -1) {

fprintf(stderr, "F_GETLK failed\n");

exit(EXIT_FAILURE);

}

if (region_to_test.l_pid != -1) {

printf("Lock would fail. F_GETLK returned:\n");

show_lock_info(&region_to_test);

} else {

printf("F_WRLCK - Lock would succeed\n");

}

region_to_test.l_type = F_RDLCK;

region_to_test.l_whence = SEEK_SET;

region_to_test.l_start = start_byte;

region_to_test.l_len = SIZE_TO_TRY;

region_to_test.l_pid = -1;

printf("Testing F_RDLCK on region from %d to %d\n",

start_byte, start_byte+SIZE_TO_TRY);

res= fcntl(file_desc, F_GETLK, &region_to_test);

if (res == -1) {

fprintf(stderr, "F_GETLK failed\n");

//show_lock_info(&region_to_test);

exit(EXIT_FAILURE);

}

if (region_to_test.l_pid != -1) {

printf("Lock would fail. F_GETLK returned:\n");

show_lock_info(&region_to_test);

} else {

printf("F_RDLCK - Lock would succeed\n");

}

}

close(file_desc);

exit(EXIT_SUCCESS);

}

void show_lock_info(struct flock *to_show) {

printf("\tl_type %d, ", to_show->l_type);

printf("l_whence %d, ", to_show->l_whence);

printf("l_start %d, ", to_show->l_start);

printf("l_len %d, ", to_show->l_len);

printf("l_pid %d\n", to_show->l_pid);

}

先执行lock3 再执行 lock4

./lock3 &

./lock4

不建议 ./lock3 & ./lock4

此处并非严格顺序执行(并行),不能保证lock3执行到sleep时lock4才执行。

建议试试:

1)对lock3 两个锁(RD WR)的区域设为同一值,看看运行结果。(估计锁的粒度 是进程/线程?)

2)将lock4 fcntl中的GETLK 改成 SETLK, 看看运行结果。(fcntl将返回-1, 而且如果此时查看flock的l_pid,发现并无修改)

注意:

1)此处的锁都是建议锁,也就是实际上还是可以对被锁文件进行读写的。(可以尝试运行lock3, 再使用gedit打开lock_file,并修改)

建议锁的作用是,至少在你访问前能得知当前是否有进程也在同时使用他。

2)最后提及一下死锁,想一下这种情况:

process A:

lock(file1);

...

sleep(10);

lock(file2);

//do someting to file2

unlock(file2);

...

unlock(file1);

process B:

lock(file2);

...

sleep(10);

lock(file1);

//do someting to file1

unlock(file1);

...

unlock(file2);

如果同时执行,对于A来说只有获取文件2,执行结束后才释放文件1.而B只有在获取文件1,执行结束后才释放A想要的文件2. 双方都拥有对方想要的元素,但是都不想退让,僵持在那里。这就是死锁。

dbm数据库

轻量级数据库,通过索引dir+文件内容pag 读写数据。

基本操作跟mysql差不多,唯一得说的是Ubuntu下,如何使用dbm:

1, 安装gdbm:

$ sudo apt-get install libgdbm-dev

2, 在c文件中使用: 头文件: #include

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值