I have problem with creating shared memory between two processes.
I getting this error, and I don't know what to do because I think a have all libraries included.
Log...
g++ exc8.c -o exc8
exc8.c: In function ‘int main(int, char**)’:
exc8.c:29:37: error: ‘ltrunc’ was not declared in this scope
size = ltrunc(fd, B_SIZE, SEEK_SET);
Code...
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#define B_SIZE 4
char* memory = new char[4];
int main(int argc, char *argv[]) {
int size, fd;
char *buf;
char memory[4];
fd = shm_open(memory, O_RDWR|O_CREAT, 0774);
if (fd < -0) {
perror("open");
exit(-1);
}
size = ltrunc(fd, B_SIZE, SEEK_SET);
if(size < 0) {
perror("trunc");
exit(-1);
}
buf = (char *)mmap(0, B_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(buf == NULL) {
perror("map");
exit(-1);
}
}
I don't know where ltrunc() comes from, but
you can set the size of a shared memory object with ftruncate():
if (ftruncate(fd, B_SIZE) == -1) {
// Handle error
}
(from http://pubs.opengroup.org/onlinepubs/009695299/functions/shm_open.html).
ltrunc is not a standard function. It seems defined in QNX Platform using qcc as the compiler, which truncates a file at given position. Probably POSIX provides the truncate() and ftruncate() functions for the job.
Related
I'm following a tutorial from BeeJ's website and i've learnt quite a bit of it.
I'm in that stage of experimentation and want to somehow build upon this code.
In short, say the user types an address: 1050576 for a file that's roughly 1000MB, the program (shown below) should map the chunk in the file data up to a position where 1050576 falls between chunk beginning and its length.
When i run the code, it says the max address size is 924 and so i can't really chunk a file that's 1000mb.
Could someone help explain / provide an example on how i can tackle this?
/*
** mmapdemo.c -- demonstrates memory mapped files lamely.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int fd, offset;
char *data;
struct stat sbuf;
if (argc != 2) {
fprintf(stderr, "usage: mmapdemo offset\n");
exit(1);
}
if ((fd = open("mmapdemo.c", O_RDONLY)) == -1) {
perror("open");
exit(1);
}
if (stat("mmapdemo.c", &sbuf) == -1) {
perror("stat");
exit(1);
}
offset = atoi(argv[1]);
if (offset < 0 || offset > sbuf.st_size-1) {
fprintf(stderr, "mmapdemo: offset must be in the range 0-%ld\n", sbuf.st_size-1);
exit(1);
}
if ((data = mmap((caddr_t)0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0)) == (caddr_t)(-1)) {
perror("mmap");
exit(1);
}
printf("byte at offset %d is '%c'\n", offset, data[offset]);
return 0;
}
I would like to do the following: I have a function in a .c file. I want to compile it, then in my main function, I want to put this object to a certain virtual address.
This is my shared function in sharedfunction.c
#include <stdio.h>
int dummy;
void sharedfunction(int x){
if(x){
dummy &= x;
}
}
I have compiled it using:
gcc -c -fPIC sharedfunction.c -o sharedfunction.o
Now, I would like to put this object to a certain virtual address in my main function.
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define pagesize 4096UL
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main() {
void *p = main;
printf("main:%p\n", p);
int fd;
struct stat sb;
off_t offset, pa_offset;
fd = open("sharedfunction.o", O_RDONLY);
if(fd == -1)
handle_error("open");
if (fstat(fd, &sb) == -1) /* To obtain file size */
handle_error("fstat");
offset = 0;
pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
/* offset for mmap() must be page aligned */
if (offset >= sb.st_size) {
fprintf(stderr, "offset is past end of file\n");
exit(EXIT_FAILURE);
}
// want to put main + 0x10_000 virtual address
void* func = mmap(
(void*) (p + 0x10000),
pagesize,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE,
fd, pa_offset);
if (func == MAP_FAILED)
handle_error("mmap");
// how can I call this?
func(10);
return 0;
}
I am compiling with:
gcc -O0 main.c -o main.o
How can I call the func?
How can I clear the memory after I am finished with that func?
I have the following simple program to create a shared memory. But this is giving
Bus error (core dumped)
This is happening only on one virtual machine and I tried the same code in mutiple VM and in every other machine this is working correctly. But only on one machine this issue is happening. Can anyone point me the issue. All my machines are running on 2.6.32-279.el6.x86_64 . Will this be a kernel issue or application issue?
#include<stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
const char *shpath="/shm_path_for_data";
void *memPtr;
shm_unlink(shpath);
int fd=0;
fd = shm_open(shpath, O_RDWR|O_CREAT|O_EXCL, 0777);
if(fd<0) {
printf("shm_open failed\n");
return 1;
}
if((ftruncate(fd, getpagesize())) <0) {
printf("Ftruncate failed\n");
return 1;
}
memPtr = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if(memPtr == MAP_FAILED) {
return 1;
}
strcpy((char *)memPtr, "test input.Just copying something\n");
printf("mapped out: %s\n", (char *)memPtr);
}
You are copying 50 bytes
memcpy((char *)memPtr, "test input.Just copying something\n", 50);
/* BTW: ^ this cast is unneeded */
there are only 36 available, so you are reading beyond the string literal, which is undefined behavior, that's why it works on one machine and fails on another, that's how undefined behavior behaves.
Try
strcpy((char *) memPtr, "Test input. Just copying something\n");
Exactly, I thought that I finished my project until compiling isn't accepted on ubuntu because of mmap(). I'm trying to access(read) files by using fork(). It's okey. But, When I want to count number of read files, entered folder(directories) and child, I powned! How and What can I use or change mmap() because I get error: ‘MAP_ANON’ undeclared (first use in this function)|
. On mac, It's okey but on ubuntu error. Thank you for helps.
#define _XOPEN_SOURCE 700
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
#include <ftw.h>
#include <ctype.h>
#include <sys/mman.h>
#define MAX_PATH_LEN 2048
static int *wordCount = 0;
static int *childCount = 0;
static int *folderCount = 0;
int relatedWord(const char *arr);
int checkWord(const char arr[], int size);
void err_sys(const char *msg);
int disp(const char *filepath, const struct stat *finfo, int flag, struct FTW *ftw);
int main(int argc, char *argv[])
{
//struct stat finfo;
//int count = 0;
wordCount = mmap(NULL, sizeof *wordCount, PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANON, -1, 0);
childCount = mmap(NULL, sizeof *childCount, PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANON, -1, 0);
folderCount = mmap(NULL, sizeof *folderCount, PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANON, -1, 0);
if (argc != 2) {
fprintf(stderr, "Wrong number of arguments!\nUsage: dirwalk6 <path>\n");
exit(EXIT_FAILURE);
}
if (nftw(argv[1], disp, 20, 0) < 0)
err_sys("ntfw");
printf( "\nTotal words = %d\n\n", *wordCount);
printf( "\nTotal folders = %d\n\n", *folderCount);
printf( "\nTotal childs = %d\n\n", *childCount);
return 0;
}
int disp(const char *filepath, const struct stat *finfo, int flag, struct FTW *ftw)
{
int count = 0; /* number of words */
switch (flag) {
case FTW_F: /* determining file */
printf("%*s%s\n", ftw->level * 4, "", filepath);
pid_t pid;
pid=fork();
if(pid < 0)
{
perror("Error corresponding to fork()");
}
else if (pid == 0)
{
count += relatedWord(filepath);
*wordCount += count;
*childCount += 1;
exit(1);
}
else
{
while( pid != wait(0) ) ;
}
// printf( "word = %d, file = %s \n", count,filepath);
break;
case FTW_D: /* determining folder */
printf("%*s%s\n", ftw->level * 4, "", filepath + ftw->base);
*folderCount += 1;
break;
}
return 0;
}
From the man page for mmap(2) (my bold):
Certain flags constants are defined only if either _BSD_SOURCE or _SVID_SOURCE is defined. (Requiring _GNU_SOURCE also suffices, and requiring that macro specifically would have been more logical, since these flags are all Linux specific.) The relevant flags are: MAP_32BIT, MAP_ANONYMOUS (and the synonym MAP_ANON), MAP_DENYWRITE, MAP_EXECUTABLE, MAP_FILE, MAP_GROWSDOWN, MAP_HUGETLB, MAP_LOCKED, MAP_NONBLOCK, MAP_NORESERVE, MAP_POPULATE, and MAP_STACK.
So you will need to define _BSD_SOURCE, _SVID_SOURCE or (if I read that right) _GNU_SOURCE at the top of the file, but in any event prior to
#include <sys/mman.h>
As per #mafso's comment, best to do this prior to any system header include (not least in case an another header itself includes <sys/mman.h>
The following C code illustrates a problem I'm seeing on Linux 2.6.30.5-43.fc11.x86_64:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
char buf[1024];
void *base;
int fd;
size_t pagesz = sysconf(_SC_PAGE_SIZE);
fd = open("<some file, at least 4*pagesz in length>", O_RDONLY);
if (fd < 0) {
perror("open");
return 1;
}
base = mmap(0, 4*pagesz, PROT_READ, MAP_SHARED, fd, 0);
if (base < 0) {
perror("mmap");
close(fd);
return 1;
}
memcpy(buf, (char*)base + 2*pagesz, 1024);
if (remap_file_pages(base, pagesz, 0, 2, 0) < 0) {
perror("remap_file_pages");
munmap(base, 4*pagesz);
close(fd);
return 1;
}
printf("%d\n", memcmp(buf, base, 1024));
munmap(base, 4*pagesz);
close(fd);
return 0;
}
This always fails with remap_file_pages() returning -1 and errno set to EINVAL. Looking at the kernel source I can see all the conditions in remap_file_pages() where it might fail but none of them seem to apply to my example. What's going on?
It's caused by the file being opened O_RDONLY. If you change the open mode to O_RDWR, it works (even if the mmap() still specifies just PROT_READ).
This code in do_mmap_pgoff is the root cause - it only marks the vma as VM_SHARED if the file was opened for writing:
vm_flags |= VM_SHARED | VM_MAYSHARE;
if (!(file->f_mode & FMODE_WRITE))
vm_flags &= ~(VM_MAYWRITE | VM_SHARED);
So in remap_file_pages(), you fail on the first check:
if (!vma || !(vma->vm_flags & VM_SHARED))
goto out;