求助,windows c++多线程问题,具体为多个程序同时读写一个文件,实现同步操作

ghost_jiusi 2019-06-08 12:26:43
自己写了一个控制台程序,功能是打开一个文件,然后有一系列的读写操作。

程序编译执行之后在项目文件夹里生成了一个exe文件。

想要实现的功能是,多次打开这个exe文件,在第一个窗口中写,能在第一个窗口中读到写入的内容,在第二个窗口也能读到写入的内容。
...全文
1265 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
636f6c696e 2019-06-09
  • 打赏
  • 举报
回复
简单写了个样例,你可以参考下. 多进程并发还要加一个mutex保证互斥,我这个样例偷懒就没写了。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>

#define DIR_MAX_NUM		100
#define FILE_MAX_NUM	100
#define DIR_MAX_NAME_LEN	20
#define FILE_MAX_NAME_LEN	20
#define DIR_MAX_DIR_NUM		10
#define DIR_MAX_FILE_NUM	10
#define USED	1
#define UNUSED	0

typedef struct file_info_s
{
    char used;
    int file_index;
    char file_name[FILE_MAX_NAME_LEN];
}file_info;

typedef struct dir_info_s
{
	char used;
    int dir_index;
	char dir_name[DIR_MAX_NAME_LEN];
	int dir_list[DIR_MAX_DIR_NUM];
	int file_list[DIR_MAX_FILE_NUM];
}dir_info;

dir_info *g_dir;
file_info *g_file;

dir_info *g_cur_dir;

int add_dir(char* dir_name)
{
	int i;	
    dir_info *dir;
	
	for (i = 1; i < DIR_MAX_NUM; i++)
	{
	    dir = &g_dir[i]; 
		if (UNUSED == dir->used)
		{
			dir->used = USED;
			dir->dir_index = i;
			strcpy(dir->dir_name, dir_name);
			return i;
		}
	}
	
	printf("No more dirs can be added.\n");	
	return 0;
}

int add_file(char* file_name)
{
	int i;	
    file_info *file;
	
	for (i = 1; i < FILE_MAX_NUM; i++)
	{
	    file = &g_file[i]; 
		if (UNUSED == file->used)
		{
			file->used = USED;
			file->file_index = i;
			strcpy(file->file_name, file_name);
			return i;
		}
	}
	
	printf("No more files can be added.\n");	
	return 0;
}

void mkdir(char* dir_name)
{
    int index;
	int i;
	
	index = add_dir(dir_name);
	if (0 == index)
	    return;
	
	for (i = 0; i < DIR_MAX_DIR_NUM; i++)
	{
		if (0 == g_cur_dir->dir_list[i])
		{
			g_cur_dir->dir_list[i] = index;
			printf("Create new dir successfully.\n");
			return;
		}
	}
	
	printf("Failed to create new dir.\n");	
}

void mkfile(char* file_name)
{
    int index;
	int i;
	
	index = add_file(file_name);
	if (0 == index)
	    return;
	
	for (i = 0; i < DIR_MAX_FILE_NUM; i++)
	{
		if (0 == g_cur_dir->file_list[i])
		{
			g_cur_dir->file_list[i] = index;
			printf("Create new file successfully.\n");
			return;
		}
	}
	
	printf("Failed to create new file.\n");	
}

void dir()
{
	dir_info *dir;
	file_info *file;
	int index;
	int i;
	
	printf("Dir list:\n");
	for (i = 0; i < DIR_MAX_DIR_NUM; i++)
	{
		index = g_cur_dir->dir_list[i];
		if (0 != index)
		{
			dir = &g_dir[index];
			printf("%s\n", dir->dir_name);
		}
	}
	
	printf("File list:\n");
	for (i = 0; i < DIR_MAX_DIR_NUM; i++)
	{
		index = g_cur_dir->file_list[i];
		if (0 != index)
		{
			file = &g_file[index];
			printf("%s\n", file->file_name);
		}
	}
}

void cd(char* dir_name)
{
	dir_info *dir;
	int index;
	int i;
	
	for (i = 0; i < DIR_MAX_DIR_NUM; i++)
	{
		index = g_cur_dir->dir_list[i];
		if (0 == strcmp(g_dir[index].dir_name, dir_name))
		{
			g_cur_dir = &g_dir[index];
			printf("Cd %s successfully.\n", dir_name);
			return;
		}
	}
	
	printf("No such dir:%s.\n", dir_name);
}

void dir_init()
{
    int fd;
	fd = open("fs.dat", O_CREAT|O_RDWR|O_TRUNC, 00777);
	lseek(fd, sizeof(dir_info) * DIR_MAX_NUM + sizeof(file_info) * FILE_MAX_NUM + 100, SEEK_SET);
	write(fd, " ", 1);
	g_dir = (dir_info *)mmap(NULL, sizeof(dir_info) * DIR_MAX_NUM + sizeof(file_info) * FILE_MAX_NUM, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
	g_file = (file_info *)((char *)g_dir + sizeof(dir_info) * DIR_MAX_NUM);
	
	// init root path
	g_dir[0].used = USED;
	g_dir[0].dir_index = 0;
	strcpy(g_dir[0].dir_name, "root");
	
	g_cur_dir = &g_dir[0];
}

int main()
{
	char cmd[100] = {0};
	char *name;
	
	dir_init();
	
	gets(cmd);
	while (0 != strcmp("exit", cmd))
	{
		//printf("Cmd is \"%s\".\n", cmd);
		if (0 == strncmp("dir", cmd, strlen("dir")))
		{
			dir();
		}
		else if (0 == strncmp("cd ", cmd, strlen("cd ")))
		{
			name = cmd + strlen("cd ");
			cd(name);
		}
		else if (0 == strncmp("mkdir ", cmd, strlen("mkdir ")))
		{
			name = cmd + strlen("mkdir ");
			mkdir(name);
		}
		else if (0 == strncmp("mkfile ", cmd, strlen("mkfile ")))
		{
			name = cmd + strlen("mkfile ");
			mkfile(name);
		}
		else
		{
			printf("Wrong input:%s.\n", cmd);
		}
		
		gets(cmd);
	}
	
	return 0;
}
进程1:
mkdir abc
Create new dir successfully.
mkdir test
Create new dir successfully.
mkfile temp
Create new file successfully.
进程2:
dir
Dir list:
abc
test
File list:
temp
636f6c696e 2019-06-09
  • 打赏
  • 举报
回复
你这种场景更应该用内存映射,如果用文件读写,每个查询操作都必须重新读取文件刷新,而内存映射可以直接获取最新的信息,效率要高很多
引用 2 楼 ghost_jiusi 的回复:
能用c语言fread fwrite实现读写嘛,因为对文件操作要精确到每一个字节,可能第一个exe改变了文件的前512个字节,第二个文件可以读到这个文件的前512个字节内容改变后的内容,同样第二个exe修改了文件 第513 到 1024 字节的内容,第一个文件读到的应该是修改之后的
636f6c696e 2019-06-09
  • 打赏
  • 举报
回复
你的诉求和fread有啥关系,难道用共享内存映射就不能保证精确?
引用 1 楼 ghost_jiusi 的回复:
能用c语言fread fwrite实现读写嘛,因为对文件操作要精确到每一个字节,可能第一个exe改变了文件的前512个字节,第二个文件可以读到这个文件的前512个字节内容改变后的内容,同样第二个exe修改了文件 第513 到 1024 字节的内容,第一个文件读到的应该是修改之后的
赵4老师 2019-06-09
  • 打赏
  • 举报
回复
_locking
Locks or unlocks bytes of a file.

int _locking( int handle, int mode, long nbytes );

Routine Required Header Optional Headers Compatibility
_locking <io.h> and <sys/locking.h> <errno.h> Win 95, Win NT


For additional compatibility information, see Compatibility in the Introduction.

Libraries

LIBC.LIB Single thread static library, retail version
LIBCMT.LIB Multithread static library, retail version
MSVCRT.LIB Import library for MSVCRT.DLL, retail version


Return Value

_locking returns 0 if successful. A return value of –1 indicates failure, in which case errno is set to one of the following values:

EACCES

Locking violation (file already locked or unlocked).

EBADF

Invalid file handle.

EDEADLOCK

Locking violation. Returned when the _LK_LOCK or _LK_RLCK flag is specified and the file cannot be locked after 10 attempts.

EINVAL

An invalid argument was given to _locking.

Parameters

handle

File handle

mode

Locking action to perform

nbytes

Number of bytes to lock

Remarks

The _locking function locks or unlocks nbytes bytes of the file specified by handle. Locking bytes in a file prevents access to those bytes by other processes. All locking or unlocking begins at the current position of the file pointer and proceeds for the next nbytes bytes. It is possible to lock bytes past end of file.

mode must be one of the following manifest constants, which are defined in LOCKING.H:

_LK_LOCK

Locks the specified bytes. If the bytes cannot be locked, the program immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, the constant returns an error.

_LK_NBLCK

Locks the specified bytes. If the bytes cannot be locked, the constant returns an error.

_LK_NBRLCK

Same as _LK_NBLCK.

_LK_RLCK

Same as _LK_LOCK.

_LK_UNLCK

Unlocks the specified bytes, which must have been previously locked.

Multiple regions of a file that do not overlap can be locked. A region being unlocked must have been previously locked. _locking does not merge adjacent regions; if two locked regions are adjacent, each region must be unlocked separately. Regions should be locked only briefly and should be unlocked before closing a file or exiting the program.

Example

/* LOCKING.C: This program opens a file with sharing. It locks
* some bytes before reading them, then unlocks them. Note that the
* program works correctly only if the file exists.
*/

#include <io.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/locking.h>
#include <share.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

void main( void )
{
int fh, numread;
char buffer[40];

/* Quit if can't open file or system doesn't
* support sharing.
*/
fh = _sopen( "locking.c", _O_RDWR, _SH_DENYNO,
_S_IREAD | _S_IWRITE );
if( fh == -1 )
exit( 1 );

/* Lock some bytes and read them. Then unlock. */
if( _locking( fh, LK_NBLCK, 30L ) != -1 )
{
printf( "No one can change these bytes while I'm reading them\n" );
numread = _read( fh, buffer, 30 );
printf( "%d bytes read: %.30s\n", numread, buffer );
lseek( fh, 0L, SEEK_SET );
_locking( fh, LK_UNLCK, 30L );
printf( "Now I'm done. Do what you will with them\n" );
}
else
perror( "Locking failed\n" );

_close( fh );
}


Output

No one can change these bytes while I'm reading them
30 bytes read: /* LOCKING.C: This program ope
Now I'm done. Do what you will with them


File Handling Routines

See Also _creat, _open
gouyanfen 2019-06-08
  • 打赏
  • 举报
回复
共享内存映射文件
gouyanfen 2019-06-08
  • 打赏
  • 举报
回复
::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(btxingxi)*MAX_BTSHULIANG, btmapfilename OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, btmapfilename); MapViewOfFile(btdituxixi, FILE_MAP_ALL_ACCESS, 0, 0, 0);
ghost_jiusi 2019-06-08
  • 打赏
  • 举报
回复
程序的内容是自己用一个二进制文件实现了一个模拟磁盘,再写一个shell对这个磁盘进行读写,模拟文件系统。
再具体点说就是先打开两个exe程序,exe打开后会进入根目录,在第一个shell 中 mkdir 一个文件夹之后在第二个 shell 中 dir 能看到刚刚创建的空目录。
ghost_jiusi 2019-06-08
  • 打赏
  • 举报
回复
能用c语言fread fwrite实现读写嘛,因为对文件操作要精确到每一个字节,可能第一个exe改变了文件的前512个字节,第二个文件可以读到这个文件的前512个字节内容改变后的内容,同样第二个exe修改了文件 第513 到 1024 字节的内容,第一个文件读到的应该是修改之后的

64,645

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧