12-18-2020 07:28 AM
how to use mmap to control a io pin in linux labview
Solved! Go to Solution.
12-18-2020 09:33 AM - edited 12-18-2020 09:34 AM
By far the easiest is to write a small shared library in C that implements the mapping in a consistent way and exports an easy to use API that you can then call using the LabVIEW Call Library Node.
In theory one could call the according libc runtime functions directly through the Call Library Node but that is a tedious and error prone path, since those APIs are meant to be called from C and not a higher level language. It also can easily fail if you try to run it on a different Linux platform since binary compatibility is not a highly valued idea under Linux (nor Unix in general).
After all you have the source available, right? And a real Linux hacker compiles absolutely everything from source code anyways, so why bother about the difficulties of trying to be binary compatible!
12-18-2020 10:09 PM - edited 12-18-2020 10:10 PM
thanks a lot ,rolfk . i want to try libc first , so i use the Call Library Node to call libc.so.6 , but i can not find mmap function in libc.so.6 , could you give me a favor ?
12-19-2020 06:01 AM
How do you conclude that it’s not there? Under Linux you don’t have the list box like in the Windows call library configuration dialog. You have to know the functions you want to call and type them in.
Also there should be a symlink on your system that links libc.so to whatever libc you have. Last but not least under Linux it is normal to leave the lib prefix away and LabVIEW supports that too, so entering c.so should be enough for the library name.
12-20-2020 10:26 PM
@Rolf Kalbermatter
12-21-2020 04:46 AM - edited 12-21-2020 04:51 AM
Nice they added the listing of exports to the Call Library Node configuration.
Only it may not seem to show all symbols!
Try this on a command line:
readelf -s /lib/libc.so.6 | grep mmap
This should give you a list of most likely two aliases for mmap64 and mmap that point to a different shared library, most likely something like glibc_2.2.something, although the version number may vary greatly depending on your Linux distribution.
An alternative may be:
scanelf -l -s mmap
but that tool is not common on all installations and I'm not quite sure which package you would have to install to get that onto your system.
Try to simply enter mmap in the function name box for a starter and see if that will cause a broken arrow. Just because the symbol is not visible as standard export, it may still be accessible.
You can of course also try to link directly to the real shared library instead that may be found through analyzing the alias above, but that is a very bad idea. These libraries change with every minor update of the Linux kernel and may change names (especially the version numbers) like an ordinary human changes his underpants. So if you access the final shared library directly, your VI will almost certainly never run on another computer system, unless it has installed exactly the same kernel too.
12-21-2020 06:20 AM
readelf display there are mmap and mmap64 , but the function name list display none .
i type mmap in function name , and the vi is runnable , why ?
//
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *start, size_t length);
Q1: mmap return void * , how could i use it in labveiw ?
Q2: param fd , use Open/Create/Replace File.vi or open function in .so to get file handle
12-21-2020 06:47 AM - edited 12-21-2020 07:02 AM
@8259 wrote:
readelf display there are mmap and mmap64 , but the function name list display none .
i type mmap in function name , and the vi is runnable , why ?
//
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *start, size_t length);
Q1: mmap return void * , how could i use it in labveiw ?
Q2: param fd , use Open/Create/Replace File.vi or open function in .so to get file handle
The function enumerating the various exported symbols seems to skip certain symbols. It may skip the symbols marked as WEAK and must skip symbols marked as LOCAL, since those are not really accessible externally. Not a problem really, just an inconvenience. Under Linux you are not supposed to enumerate shared library symbols anyhow. Instead you simply use the dlsym() function with RTLD_NEXT as first parameter and all is well. The dynamic loader will scan all loaded shared libraries for that symbol and resolve them. And when programming in C you don't even load symbols dynamically normally but simply use them and let the compiler and linker do the rest.
a void* is simply a pointer (you see the asterix?) without any type definition to what it is pointing at. In LabVIEW this corresponds to a pointer sized (unsigned) integer.
And no, the fd is not equivalent to the refnum returned by the Open/Create/Replace node. A LabVIEW refnum is a reference to a LabVIEW internal struct that identifies the resource by various means depending on the resource. It contains internally a File* pointer which is a LabVIEW pointer to a private data structure that then contains the platform specific file identifier, except that this is also not a fd integer, but rather a FILE* pointer on Linux which is yet another libc private data structure that you are not supposed to reference in any other way than by using other libc functions that accept such a parameter. There are some other libc functions that can then map the FILE* into a file descriptor and vice versa.
The easiest is to actually simply call the open() function in libc too, which will return you the according file descriptor. And as you can see, calling this "simple" function directly through the Call Library Node, quickly turns into a major exercise in calling several more system functions, and very soon you realize that writing a wrapper shared library in C is actually going to be easier.
That is if you know how to program in C. However your questions indicate to me, that you are in for a rough ride in trying to interface this API from LabVIEW through the Call Library Node. It's not a shortcut in trying to avoid to write a wrapper DLL in C. In fact you need all the knowledge to access the functions from a real C program and then some, to be able to use the Call Library Node properly!
12-21-2020 07:34 AM
more about Q1 , in c language , i can easily write one or more bytes data in ram by the pointer like
*((char *)pointer) = 1 , *((int *)pointer) = 1 , but in labview , when i get the pointer by mmap() function , how could i use the pointer to RW data in ram
12-21-2020 07:40 AM - edited 12-21-2020 07:45 AM
By using the MoveBlock() function through yet another Call Library Node. LabVIEW has for various reasons no built in functionality to access pointer data from the diagram. This goes completely against dataflow programming, which is the basic principle used in the LabVIEW diagram.
For every data element in your pointer you have to calculate the appropriate offset, add that offset to the basic address and then call the function:
void MoveBlock(void *source, void *target, size_t numBytes);
Use LabVIEW as library name in the Call Library Node to access this function.
All LabVIEW exported functions use cdecl calling convention (important when calling functions under Windows).
In source you pass in the pointer to the data you want to copy into, in target you pass in your pointer adjusted for the correct offset, and in length the size in bytes of the data.
For reading from that pointer you simply exchange the target and source.
Did I ever mention that writing a wrapper shared library is actually a good idea? 😁