Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How memory mapping files are accessed as a variable?If not, is it possible? #42736

Closed
maikebing opened this issue Sep 25, 2020 · 11 comments
Closed
Assignees
Labels
area-System.IO question Answer questions and provide assistance, not an issue with source code or documentation.
Milestone

Comments

@maikebing
Copy link

maikebing commented Sep 25, 2020

C code

foo*  __filemap = mmap(NULL, filesizemaybe, PROT_READ, MAP_SHARED | MAP_LOCKED, _FD, 0);
printf(foo[0].a);

C# now

   var mmf = MemoryMappedFile.CreateFromFile(fi.FullName, FileMode.Open, "MyFile");
                        var cva1 = mmf.CreateViewAccessor(0, rawsize);

                        var cva = mmf.CreateViewAccessor(rawsize, fi.Length - rawsize);
                        arys = new blackdic[head.Total];
                        cva.ReadArray<blackdic>(0, arys, 0, head.Total);
                        cva.Dispose();
                        mmf.Dispose();

Memory needs to be allocated.

C# hope

   var mmf = MemoryMappedFile.CreateFromFile(fi.FullName, FileMode.Open, "MyFile");
var cva = mmf.CreateViewAccessor(0, rawsize);
blackdic[] foo=  cva.Map<blackdic>(0, arys, 0, head.Total);

This way we don't need to allocate extra memory, so we can use the files on the disk as memory pointers.

@maikebing maikebing added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Sep 25, 2020
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added area-System.IO untriaged New issue has not been triaged by the area owner labels Sep 25, 2020
@huoyaoyuan
Copy link
Member

#37227

@stephentoub
Copy link
Member

You can get at the raw pointer if that's what you want to use:

var mmf = MemoryMappedFile.CreateFromFile(...);
var va = mmf.CreateViewAccessor();
byte* ptr = null;
va.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr);
try
{
    ulong length = va.SafeMemoryMappedViewHandle.ByteLength;
    ... // use ptr and length here
}
finally
{
    va.SafeMemoryMappedViewHandle.ReleasePointer();
}

@stephentoub
Copy link
Member

(Also, #40842 added a ReadSpan method to go along with ReadArray, but that didn't make it into the .NET 5 release.)

@stephentoub
Copy link
Member

@maikebing, when you get a chance, please let us know if there's something further you think is needed here or whether this issue can be closed. Thanks!

@carlossanlop carlossanlop added question Answer questions and provide assistance, not an issue with source code or documentation. and removed api-suggestion Early API idea and discussion, it is NOT ready for implementation untriaged New issue has not been triaged by the area owner labels Sep 25, 2020
@maikebing
Copy link
Author

My struct is this code !

  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct blackdic
    {
  
        [MarshalAs(UnmanagedType.U4, SizeConst = 4)]
        public uint issuerid;//4
   
        [MarshalAs(UnmanagedType.U2, SizeConst = 2)]
        public ushort cardhead;//2
    
        [MarshalAs(UnmanagedType.U8, SizeConst = 8)]
        public ulong cardid; //8
    
        [MarshalAs(UnmanagedType.U1, SizeConst = 1)]
        public byte cardtype; //1
        [MarshalAs(UnmanagedType.U1, SizeConst = 1)]
        public byte blacktype;//1
    }

blackdic* bdc = null;
byte* bytex = null;
cva.SafeMemoryMappedViewHandle.AcquirePointer(ref bytex);
bdc = (blackdic*)bytex;

The value does not match the actual value.

@stephentoub
Copy link
Member

The value does not match the actual value.

What values are you expecting and what values are you getting?

Can you share a standalone small repro that can be run, showing what output your getting and what output you're expecting to get?

@maikebing
Copy link
Author

@stephentoub
Copy link
Member

Thanks. The issue has to do with the offset. CreateViewAccessor may page-align the offset and size provided, in order to create a page-aligned view. The Read methods on the returned MemoryMappedViewAccessor then explicitly factor the offset into the calculations (e.g. if you provided an offset of 4050, that might get rounded down internally to 4096 to page-align, and then calls to Read will ensure whatever byte index you provide is incremented by the remaining 4 offset). But when you ask to acquire the pointer, that's just giving back the raw pointer to the beginning of the page-aligned view, so you need to manually factor in the offset, which is available from the PointerOffset property. In other words, in your repro, instead of:

blackdic* _bd_ptr = (blackdic*)ptr;

you need to do:

blackdic* _bd_ptr = (blackdic*)(ptr + cva.PointerOffset);

(The docs could probably be improved in this area.)

@maikebing
Copy link
Author

Thank you for your help, solve my big trouble.

@stephentoub
Copy link
Member

Actually, I may have steered you wrong / there may be a bug here... I need to look into this more; will do so on Monday. Thanks.

@stephentoub stephentoub reopened this Sep 27, 2020
@stephentoub stephentoub self-assigned this Sep 27, 2020
@stephentoub stephentoub added this to the 6.0.0 milestone Sep 27, 2020
@stephentoub
Copy link
Member

Nope, I was right, the docs just need to be corrected in a few places. I'll take care of that. Thanks.

@ghost ghost locked as resolved and limited conversation to collaborators Dec 7, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.IO question Answer questions and provide assistance, not an issue with source code or documentation.
Projects
None yet
Development

No branches or pull requests

5 participants