我的“主要”功能中有这段代码。
...
int data_size1 = sizeof(dados);
int fdDados = shm_open("/dados", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
if (fdDados<0){
perror("shm_open failed");
exit(1);
}
dados* shared_data_dados=(dados*) mmap(NULL, data_size1, PROT_READ|PROT_WRITE, MAP_SHARED, fdDados, 0);
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime (&rawtime);
char auxMsg[91];
sprintf(auxMsg, "Pid=%d, time=%s", getpid(), asctime(timeinfo));
printf(auxMsg);
strcpy((shared_data_dados->msg), auxMsg);
...
它包括以下.h:
typedef struct {
char msg[101];
} dados;
问题是,当我对结构执行strcpy时,它会给我一个总线错误。我已经尝试将结构更改为char *,并在strcpy的原始部分放置一个char *但我仍然得到相同的错误。 printf打印正确的“消息”,这不应该是问题...
任何帮助都是相关的。
提前致谢!
答案 0 :(得分:2)
您需要调用ftruncate(fdDados, SIZE)
来定义共享内存对象的大小(SIZE
),如man 3 shm_open
手册页中所述。
默认情况下,共享内存对象的大小为零字节。由于您的映射不受共享内存对象的支持,因此对映射的所有访问都会导致生成SIGBUS
信号。
这与内存映射文件时的情况完全相同,然后尝试访问文件末尾的映射。
在mmap()
调用中,第二个参数(映射的长度)应为页面大小的倍数。
您可以致电sysconf(_SC_PAGESIZE)
获取页面尺寸。不要依赖魔术常量或预处理器宏。
由于上面的(1)和(2),最好通过将所需的共享内存量四舍五入到下一个页面大小来计算SIZE
。例如:
static size_t full_pages(const size_t size)
{
size_t page = sysconf(_SC_PAGESIZE);
if (size < page)
return page;
else
if (size % page)
return size + page - (size % page);
else
return size;
}
并在您的代码中
int shared_fd, len;
size_t shared_size;
dados *shared_dados;
shared_size = full_pages(sizeof *shared_dados);
shared_fd = shm_open("/dados", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
if (shared_fd == -1) {
fprintf(stderr, "Cannot create shared object '/dados': %s.\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (ftruncate(shared_fd, (off_t)shared_size) == -1) {
fprintf(stderr, "Cannot resize shared object '/dados': %s.\n", strerror(errno));
exit(EXIT_FAILURE);
}
shared_dados = mmap(NULL, shared_size, PROT_READ | PROT_WRITE,
MAP_SHARED, shared_fd, 0);
if (shared_dados == MAP_FAILED) {
fprintf(stderr, "Cannot map shared object '/dados': %s.\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (close(shared_fd) == -1) {
fprintf(stderr, "Error closing shared object '/dados': %s.\n", strerror(errno));
exit(EXIT_FAILURE);
} else
shared_fd = -1;
/* TODO: LOCKING! */
memset(shared_dados->msg, '\0', sizeof shared_dados->msg);
len = snprintf(shared_dados->msg, sizeof shared_dados->msg, "pid=%ld", (long)getpid());
if (len < 0 || len >= (int)sizeof shared_dados->msg) {
/* The string we tried to print was too long to
fit into the shared_dados->msg field. Oops. */
}
请注意,我假设msg
结构中的dados
成员是一个char数组。如果它是指向char的指针,它将无法工作。 (它将指向一些随机位置。即使您将其设置为指向此进程中的共享内存对象 ,它也会指向其他进程中的错误地址,因为映射基本上是在随机地址。)
另请注意TODO: LOCKING!
评论。为确保其他流程只能看到完整的消息,您应该使用例如访问msg
成员的互斥锁。