Class: Win32::MMap
- Inherits:
-
Object
- Object
- Win32::MMap
- Includes:
- Windows::Constants, Windows::Functions, Windows::Structs
- Defined in:
- lib/win32/mmap.rb
Overview
The MMap class encapsulates functions for memory mapped files.
Constant Summary collapse
- VERSION =
The version of the win32-mmap library.
'0.4.2'
Instance Attribute Summary collapse
-
#access ⇒ Object
Access desired to the file mapping object.
-
#address ⇒ Object
readonly
The address of the file view mapping.
-
#autolock ⇒ Object
writeonly
Sets whether or not a semaphore lock is automatically placed on the mapped view for read and write operations.
-
#base_address ⇒ Object
Suggested starting address of mapped view.
-
#file ⇒ Object
The name of the file from which to create a mapping object.
-
#name ⇒ Object
A string that determines the name of the mapping object.
-
#protection ⇒ Object
The protection for the file view.
-
#size ⇒ Object
The maximum size for the file mapping object.
-
#timeout ⇒ Object
The value, in milliseconds, used to wait on the semaphore lock.
Class Method Summary collapse
-
.open(name, opts = {}, &block) ⇒ Object
Opens an existing file mapping using
name
.
Instance Method Summary collapse
-
#autolock? ⇒ Boolean
Returns whether or not a semaphore lock is automatically placed on the mapped view for read and write operations.
-
#close ⇒ Object
Unmaps the file view and closes all open file handles.
-
#flush(num_bytes = 0) ⇒ Object
Writes
num_bytes
to the disk within a mapped view of a file, or to the end of the mapping ifnum_bytes
is not specified. -
#inherit=(bool) ⇒ Object
Sets whether or not the mapping handle can be inherited by child processes.
-
#inherit? ⇒ Boolean
Returns whether or not the mapping handle can be inherited by child processes.
-
#initialize(opts = {}) ⇒ MMap
constructor
:call-seq: MMap.new(opts = {}) MMap.new(opts = {}){ |address| block }.
-
#read_string(length = @size) ⇒ Object
Reads a string of a given length from the beginning of the file if no length is given, reads the file with the @size attribute of this instance.
-
#write_string(content) ⇒ Object
Writes a string directly to the underlying file.
Constructor Details
#initialize(opts = {}) ⇒ MMap
:call-seq:
MMap.new(opts = {})
MMap.new(opts = {}){ |address| block }
Creates and returns a new Win32::MMap object. If file
is set, then that file is used to create the mapping. If a block is provided the address is yielded and the mapping object is automatically closed at the end of the block.
Accepts any one of the following hash attributes:
-
protection
-
size
-
access
-
inherit
-
name
-
base_address
-
autolock
-
timeout
-
file
Please see the documentation on the individual attributes for further details. Note that, although these are accessors, they must be set in the constructor (if set at all). Setting them after the call to MMap.new will not have any effect.
Example
require 'win32/mmap'
require 'windows/msvcrt/string'
include Windows::MSVCRT::String
include Win32
# Reverse the contents of a file.
mmap = MMap.new(:file => 'test.txt') do |addr|
strrev(addr)
end
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/win32/mmap.rb', line 133 def initialize(opts = {}) valid = %w[ file name protection access inherit size base_address open autolock timeout ] @open = nil @file = nil @autolock = nil # Validate the keys, handle inherit specially. opts.each{ |key, value| key = key.to_s.downcase unless valid.include?(key) raise ArgumentError, "Invalid key '#{key}'" end if key == 'inherit' self.inherit = value # To force inherit= method call else instance_variable_set("@#{key}", value) end } @protection ||= PAGE_READWRITE @access ||= FILE_MAP_WRITE @size ||= 0 @inherit ||= nil @base_address ||= 0 @timeout ||= 10 # Milliseconds self.inherit = false unless @inherit @hash = {} # Anything except an explicit false means the autolock is on. @autolock = true unless @autolock == false @lock_flag = 0 # Internal use only if @file if File.exists?(@file) fsize = File.size(@file) raise ArgumentError, 'cannot open 0 byte file' if fsize.zero? @size = fsize if @size < fsize end rights = GENERIC_READ|GENERIC_WRITE @fh = CreateFile(@file, rights, 0, nil, OPEN_ALWAYS, 0, 0) if @fh == INVALID_HANDLE_VALUE raise SystemCallError.new('CreateFile', FFI.errno) end else @fh = INVALID_HANDLE_VALUE end if @open @mh = OpenFileMapping(@access, @inherit[:bInheritHandle], @name) raise SystemCallError.new('OpenFileMapping', FFI.errno) if @mh == 0 else @mh = CreateFileMapping(@fh, @inherit, @protection, 0, @size, @name) raise SystemCallError.new('CreateFileMapping', FFI.errno) if @mh == 0 end if @open @address = MapViewOfFileEx(@mh, @access, 0, 0, 0, @base_address) @size = get_view_size() else @address = MapViewOfFileEx(@mh, @access, 0, 0, 0, @base_address) end if @address == 0 raise SystemCallError.new('MapviewOfFileEx', FFI.errno) end if @autolock @semaphore = CreateSemaphore(nil, 1, 1, "#{@name}.ruby_lock") if @semaphore == 0 raise Error, get_last_error end end if block_given? begin yield @address ensure close end end @address end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_id, *args) ⇒ Object (private)
This is used to allow dynamic getters and setters between memory mapped objects. – This replaces the getvar/setvar API from 0.1.0.
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
# File 'lib/win32/mmap.rb', line 323 def method_missing(method_id, *args) method = method_id.id2name args = args.first if args.length == 1 if method[-1,1] == '=' # Setter method.chop! @hash["#{method}"] = args lock_pattern do instance_variable_set("@#{method}", args) marshal = Marshal.dump(@hash) ptr = FFI::Pointer.new(:char, @address) ptr.write_string(marshal,marshal.length) end else # Getter lock_pattern do buf = FFI::MemoryPointer.new(:char, @size) ptr = FFI::Pointer.new(:char, @address) buf = ptr.read_string(@size) hash = Marshal.load(buf) val = hash["#{method}"] instance_variable_set("@#{method}", val) end return instance_variable_get("@#{method}") end end |
Instance Attribute Details
#access ⇒ Object
Access desired to the file mapping object. This may be any of the following values:
-
FILE_MAP_WRITE
-
FILE_MAP_READ
-
FILE_MAP_COPY
-
FILE_MAP_ALL_ACCESS
The default access is FILE_MAP_WRITE.
67 68 69 |
# File 'lib/win32/mmap.rb', line 67 def access @access end |
#address ⇒ Object (readonly)
The address of the file view mapping.
71 72 73 |
# File 'lib/win32/mmap.rb', line 71 def address @address end |
#autolock=(value) ⇒ Object (writeonly)
Sets whether or not a semaphore lock is automatically placed on the mapped view for read and write operations. This is true by default.
89 90 91 |
# File 'lib/win32/mmap.rb', line 89 def autolock=(value) @autolock = value end |
#base_address ⇒ Object
Suggested starting address of mapped view. If this value is not specified, the system will choose the base mapping address. If you do specify a value, it must be a multiple of the system’s allocation granularity.
Note: The MSDN documentation recommends that, in most case cases, you should not set this value. – A system’s allocation granularity can be found via GetSystemInfo() and the dwAllocationGranularity member of the SYSTEM_INFO struct.
84 85 86 |
# File 'lib/win32/mmap.rb', line 84 def base_address @base_address end |
#file ⇒ Object
The name of the file from which to create a mapping object. This value may be nil.
21 22 23 |
# File 'lib/win32/mmap.rb', line 21 def file @file end |
#name ⇒ Object
A string that determines the name of the mapping object. By default this value is nil, i.e. anonymous. If you specify a name
that already exists then an attempt is made to access that object.
49 50 51 |
# File 'lib/win32/mmap.rb', line 49 def name @name end |
#protection ⇒ Object
The protection for the file view. This may be any of the following values:
-
PAGE_READONLY
-
PAGE_READWRITE
-
PAGE_WRITECOPY
-
PAGE_WRITECOPY
-
PAGE_EXECUTE_READ
-
PAGE_EXECUTE_READWRITE
You can OR the protection value with any of these section attributes:
-
SEC_COMMIT
-
SEC_IMAGE
-
SEC_LARGE_PAGES
-
SEC_NOCACHE
-
SEC_RESERVE
The default protection is PAGE_READWRITE.
43 44 45 |
# File 'lib/win32/mmap.rb', line 43 def protection @protection end |
#size ⇒ Object
The maximum size for the file mapping object. If a file
is specified, this value defaults to the size of file
. Otherwise it defaults to zero (though you should set it manually).
55 56 57 |
# File 'lib/win32/mmap.rb', line 55 def size @size end |
#timeout ⇒ Object
The value, in milliseconds, used to wait on the semaphore lock. Only used if the autolock
option is true. The default is 10 milliseconds.
94 95 96 |
# File 'lib/win32/mmap.rb', line 94 def timeout @timeout end |
Class Method Details
.open(name, opts = {}, &block) ⇒ Object
Opens an existing file mapping using name
. You may pass a hash of opts
as you would to MMap.new. If you don’t specify a size as part of the opts
, it will be dynamically determined for you (in blocks equal to your system’s page size, typically 4k).
This method is otherwise identical to MMap.new. – This forces MMap.new to use OpenFileMapping() behind the scenes.
238 239 240 241 242 |
# File 'lib/win32/mmap.rb', line 238 def self.open(name, opts={}, &block) opts[:name] = name opts[:open] = true self.new(opts, &block) end |
Instance Method Details
#autolock? ⇒ Boolean
Returns whether or not a semaphore lock is automatically placed on the mapped view for read and write operations. This is true by default.
291 292 293 |
# File 'lib/win32/mmap.rb', line 291 def autolock? @autolock end |
#close ⇒ Object
Unmaps the file view and closes all open file handles. You should always call this when you are finished with the object (when using the non-block form).
281 282 283 284 285 286 |
# File 'lib/win32/mmap.rb', line 281 def close UnmapViewOfFile(@address) if @address CloseHandle(@fh) if @fh CloseHandle(@mh) if @mh ReleaseSemaphore(@semaphore, 1, nil) if @semaphore end |
#flush(num_bytes = 0) ⇒ Object
Writes num_bytes
to the disk within a mapped view of a file, or to the end of the mapping if num_bytes
is not specified.
271 272 273 274 275 |
# File 'lib/win32/mmap.rb', line 271 def flush(num_bytes = 0) unless FlushViewOfFile(@address, num_bytes) SystemCallError.new('FlushViewOfFile', FFI.errno) end end |
#inherit=(bool) ⇒ Object
Sets whether or not the mapping handle can be inherited by child processes. – If true, we have to create a SECURITY_ATTRIBUTES struct and set its nLength member to 12 and its bInheritHandle member to TRUE.
250 251 252 253 254 255 256 257 258 259 |
# File 'lib/win32/mmap.rb', line 250 def inherit=(bool) @inherit = SECURITY_ATTRIBUTES.new @inherit[:nLength] = SECURITY_ATTRIBUTES.size if bool @inherit[:bInheritHandle] = true else @inherit[:bInheritHandle] = false end end |
#inherit? ⇒ Boolean
Returns whether or not the mapping handle can be inherited by child processes. The default is false.
264 265 266 |
# File 'lib/win32/mmap.rb', line 264 def inherit? @inherit and @inherit[:bInheritHandle] end |
#read_string(length = @size) ⇒ Object
Reads a string of a given length from the beginning of the file if no length is given, reads the file with the @size attribute of this instance
306 307 308 309 310 311 312 |
# File 'lib/win32/mmap.rb', line 306 def read_string(length = @size) lock_pattern do FFI::MemoryPointer.new(:char, length) ptr = FFI::Pointer.new(:char, @address) ptr.read_string(length) end end |
#write_string(content) ⇒ Object
Writes a string directly to the underlying file
296 297 298 299 300 301 |
# File 'lib/win32/mmap.rb', line 296 def write_string(content) lock_pattern do ptr = FFI::Pointer.new(:char, @address) ptr.write_string(content,content.length) end end |