Last active
June 8, 2022 12:26
-
-
Save jorben/c56e85c96845a866f95e to your computer and use it in GitHub Desktop.
mmap写文件,多进程
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <errno.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <sys/mman.h> | |
#include <sys/sem.h> | |
#include <fcntl.h> | |
#define DFN_SEM_KEY 0xA001FFFF | |
typedef enum | |
{ | |
false, | |
true | |
}bool; | |
static int g_sem_id = -1; | |
int io(char* filename, char* buf, size_t len); | |
uint64_t getCurrTimeUs() | |
{ | |
struct timeval stTime; | |
gettimeofday(&stTime,NULL); | |
long long tmpTime = stTime.tv_sec * 1000000ull; | |
return tmpTime + stTime.tv_usec; | |
} | |
static bool s_wait_sem(); | |
static void s_unlock_sem(); | |
int main(int argc, char** argv) | |
{ | |
size_t i; | |
uint64_t t_begin = getCurrTimeUs(); | |
char* chFileName = "./log_mmap.txt"; | |
for(i=0; i<30; i++) | |
{ | |
pid_t pid = fork(); | |
if(0 == pid) | |
{ | |
size_t j; | |
char tmp[32], buf[64]; | |
int son_pid = getpid(); | |
memset(tmp, '\0', sizeof(tmp)); | |
snprintf(tmp, sizeof(tmp), "%s_%u", chFileName, son_pid); | |
uint64_t t_son_begin = getCurrTimeUs(); | |
for(j=0; j<10000; j++) | |
{ | |
memset(buf, '\0', sizeof(buf)); | |
snprintf(buf, sizeof(buf), "pid: %u, i:%zu, j:%zu\n", son_pid, i, j); | |
#if defined _UN_LOCK_ | |
// 按进程分文件 无锁写入 | |
io(tmp, buf, strlen(buf)); | |
// io(chFileName, buf, strlen(buf)); | |
#else | |
// 多进程进程写入 带锁 | |
io(chFileName, buf, strlen(buf)); | |
#endif | |
// usleep(1000); | |
} | |
printf("son:%u time cost(us):%lu\n", son_pid, getCurrTimeUs() - t_son_begin); | |
exit(0); | |
} | |
} | |
printf("time cost(us):%lu\n", getCurrTimeUs() - t_begin); | |
return 0; | |
} | |
int io(char* filename, char* buf, size_t len) | |
{ | |
int pos = 0; | |
int fd = open(filename, O_CREAT | O_RDWR, 00600); | |
if (-1 == fd) | |
{ | |
perror("open error"); | |
return -1; | |
} | |
if(s_wait_sem()) | |
{ | |
// 获取锁 后进行占位 | |
pos = lseek(fd, 0, SEEK_END); | |
lseek(fd, len-1, SEEK_END); | |
write(fd, "", 1); | |
s_unlock_sem(); | |
} | |
int dwMapLen = len + pos; | |
char * p_map = (char*)mmap(NULL, dwMapLen, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); | |
if(p_map == MAP_FAILED) | |
{ | |
close(fd); | |
perror("mmap error"); | |
return -1; | |
} | |
close(fd); | |
memcpy(p_map+pos, buf, len); | |
munmap(p_map, dwMapLen); | |
return 0; | |
} | |
static void s_unlock_sem() | |
{ | |
if(0 > g_sem_id) | |
return ; | |
struct sembuf lock; | |
lock.sem_num = 0; | |
lock.sem_op = 1; | |
lock.sem_flg = SEM_UNDO; // 进程退出(正常或非正常)时可以自动释放锁 | |
semop(g_sem_id, &lock, 1); | |
return ; | |
} | |
// 创建/打开 只允许一个进程进行P操作的信号量,并等待它 | |
static bool s_wait_sem() | |
{ | |
#if defined _UN_LOCK_ | |
return true; | |
#endif | |
g_sem_id = semget(DFN_SEM_KEY, 1, IPC_CREAT|IPC_EXCL|0666); | |
if (g_sem_id >= 0) | |
{ | |
// 计算机重启后,首次启动进程 | |
union semun { | |
int val; | |
struct semid_ds *buf; | |
unsigned short *array; | |
} arg; | |
arg.val = 1; // 只允许一个进程P操作 | |
int n = semctl(g_sem_id, 0, SETVAL, arg); | |
if (n != 0) | |
{ | |
semctl(g_sem_id, 0, IPC_RMID); | |
return false; | |
} | |
} | |
else | |
{ | |
// 可能已经存在,尝试打开 | |
g_sem_id = semget(DFN_SEM_KEY, 1, IPC_CREAT|0666); | |
if (g_sem_id < 0) | |
{ | |
return false; | |
} | |
} | |
struct sembuf lock; | |
lock.sem_num = 0; | |
lock.sem_op = -1; | |
lock.sem_flg = SEM_UNDO; // 进程退出(正常或非正常)时可以自动释放锁 | |
int n = semop(g_sem_id, &lock, 1); // 只有一个进程能够获得锁,其他进程会卡在这里等待 | |
if (n != 0) | |
{ | |
semctl(g_sem_id, 0, IPC_RMID); | |
return false; | |
} | |
return true; | |
} |
Author
jorben
commented
Dec 5, 2015
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment