July 16th Monday (七月 十六日 月曜日)

  Mapped memory permits different processes to communicate via a shared file.
Although you can think of mapped memory as using a shared memory segment
with a name,you should be aware that there are technical differences.Mapped
memory can be used for interprocess communication or as an easy way to access
the contents of a file.

  Mapped memory forms an association between a file and a process’s memory.
Linux splits the file into page-sized chunks and then copies them into virtual memory
pages so that they can be made available in a process’s address space.Thus,the process
can read the file’s contents with ordinary memory access.It can also modify the file’s
contents by writing to memory.This permits fast access to files.

  You can think of mapped memory as allocating a buffer to hold a file’s entire con-
tents,and then reading the file into the buffer and (if the buffer is modified) writing
the buffer back out to the file afterward.Linux handles the file reading and writing
operations for you.

  To map an ordinary file to a process’s memory, use the mmap (“Memory MAPped,”
pronounced “em-map”) call.  The first argument is the address at which you would like
Linux to map the file into your process’s address space;the value NULL allows Linux
to choose an available start address.The second argument is the length of the map in
bytes.The third argument specifies the protection on the mapped address range.The
protection consists of a bitwise “or”of PROT_READ, PROT_WRITE, and PROT_EXEC,
corresponding to read, write, and execution permission, respectively.  The fourth
argument is a flag value that specifies additional options.  The fifth argument is
a file descriptor opened to the file to be mapped.The last argument is the offset
from the beginning of the file from which to start the map.  You can map all or part
of the file into memory by choosing the starting offset and length appropriately.

The flag value is a bitwise “or”of these constraints:

* MAP_FIXED -- If you specify this flag,Linux uses the address you request to map
  the file rather than treating it as a hint.This address must be page-aligned.

* MAP_PRIVATE--Writes to the memory range should not be written back to the
  attached file,but to a private copy of the file.No other process sees these writes.
  This mode may not be used with MAP_SHARED.

* MAP_SHARED--Writes are immediately reflected in the underlying file rather than
  buffering writes.Use this mode when using mapped memory for IPC.This
  mode may not be used with MAP_PRIVATE.

  If the call succeeds,it returns a pointer to the beginning of the memory.  On failure,
it returns MAP_FAILED.

  When you’re finished with a memory mapping, release it by using munmap.  Pass it
thestart address and length of the mapped memory region.  Linux automatically unmaps
mapped regions when a process terminates.

  Different processescan communicate using memory-mapped regions associated with
the same file.  Specify the MAP_SHARED flag so that any writes to these regions are
immediately transferred to the underlying file and made visible to other processes.
If you don’t specify this flag,  Linux may buffer writes before transferring them to
the file.

  Alternatively, you can force Linux to incorporate buffered writes into the disk file
by calling msync.  Its first two parameters specify a memory-mapped region, as for munmap.
The third parameter can take these flag values:

* MS_ASYNC--The update is scheduled but not necessarily run before the call
  returns.

* MS_SYNC--The update is immediate; the call to msync blocks until it’s done.
  MS_SYNC and MS_ASYNC may not both be used.

* MS_INVALIDATE--All other file mappings are invalidated so that they can see the
  updated values.

  For example,to flush a shared file mapped at address mem_addr of length mem_length
bytes, call this:

  msync(mem_addr, mem_length, MS_SYNC | MS_INVALIDATE);

  As with shared memory segments, users of memory-mapped regions must establish
and follow a protocol to avoid race conditions.  For example,a semaphore can be used
to prevent more than one process from accessing the mapped memory at one time.
Alternatively,  you can use fcntl to place a read or write lock on the file.

  Specifying MAP_PRIVATE to mmap createsa copy-on-write region.  Any write to the
region is reflected only in this process’s memory;  other processes that map the same
file won’t see the changes.  Instead of writing directly to a page shared by all processes,
the process writes to a private copy of this page.All subsequent reading and writing by
the process use this page.

  The mmap call can be used for purposes other than interprocess communications.One
common use is as a replacement for read and write.  For example,rather than explic-
itly reading a file's contents into memory, a program might map the file into memory
and scan it using memory reads.For some programs, this is more convenient and may
also run faster than explicit file I/O operations.

  One advanced and powerful technique used by some programs is to build data
structures (ordinary struct instances, for example) in a memory-mapped file.  On a
subsequent invocation, the program maps that file back into memory,and the data
structures are restored to their previous state.  Note, though, that pointers in
these data structures will be invalid unless they all point within the same mapped
region of memory and unless care is taken to map the file back into the same address
region that it occupied originally.

  Another handy technique is to map the special /dev/zero file into memory.  That
file behaves as if it were an infinitely long file filled with 0 bytes.  A program
that needs a source of 0 bytes can mmap the file /dev/zero.  Writes to /dev/zero are
discarded, so the mapped memory may be used for any purpose.Custom memory allocators
often map /dev/zero to obtainchunks of preinitialized memory.

  After memoryhas been mapped,these permissions can be modified with the
mprotect system call.The arguments to mprotect are an address of a memory region,
the size of the region,and a set of protection flags.The memory region must consist of
entire pages:The address of the region must be aligned to the system’s page size,and
the length of the region must be a page size multiple.The protection flags for these
pages are replaced with the specified value.
 
获取每个月最后一个非节假日的工作日可以分为三步: 1. 获取当月最后一天 2. 如果最后一天是周六或周日,则向前推到最后一个工作日 3. 如果最后一天是节假日,则不断向前推到最后一个非节假日的工作日 以下是一个示例代码: ```java import java.time.DayOfWeek; import java.time.LocalDate; import java.time.Month; import java.time.temporal.TemporalAdjusters; public class LastWorkdayOfMonthWithoutHolidayExample { public static void main(String[] args) { int year = 2021; Month[] months = {Month.JANUARY, Month.FEBRUARY, Month.MARCH, Month.APRIL, Month.MAY, Month.JUNE, Month.JULY, Month.AUGUST, Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER, Month.DECEMBER}; for (Month month : months) { // 获取当月最后一天 LocalDate lastDayOfMonth = LocalDate.of(year, month, 1) .with(TemporalAdjusters.lastDayOfMonth()); // 如果最后一天是周六或周日,则向前推到最后一个工作日 DayOfWeek lastDayOfWeek = lastDayOfMonth.getDayOfWeek(); if (lastDayOfWeek == DayOfWeek.SATURDAY || lastDayOfWeek == DayOfWeek.SUNDAY) { lastDayOfMonth = lastDayOfMonth.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY)); } // 如果最后一天是节假日,则向前推到最后一个非节假日的工作日 while (isHoliday(lastDayOfMonth)) { lastDayOfMonth = lastDayOfMonth.minusDays(1); } System.out.println(month + "月最后一个非节假日的工作日:" + lastDayOfMonth); } } // 判断一个日期是否是节假日 private static boolean isHoliday(LocalDate date) { // 这里假设元旦、春节、清明节、劳动节、端午节、中秋节和国庆节都是节假日 return date.getMonth() == Month.JANUARY && date.getDayOfMonth() == 1 || isSpringFestival(date) || date.getMonth() == Month.APRIL && date.getDayOfMonth() == 4 || date.getMonth() == Month.MAY && date.getDayOfMonth() == 1 || isDragonBoatFestival(date) || isMidAutumnFestival(date) || date.getMonth() == Month.OCTOBER && date.getDayOfMonth() == 1 || date.getMonth() == Month.OCTOBER && date.getDayOfMonth() == 2 || date.getMonth() == Month.OCTOBER && date.getDayOfMonth() == 3; } // 判断一个日期是否是春节 private static boolean isSpringFestival(LocalDate date) { int year = date.getYear(); LocalDate springFestival = LocalDate.of(year, Month.JANUARY, 1) .with(TemporalAdjusters.firstDayOfNextMonth()) .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); if (springFestival.getMonth() == Month.FEBRUARY) { springFestival = springFestival.minusDays(7); } return date.equals(springFestival) || date.equals(springFestival.plusDays(1)) || date.equals(springFestival.plusDays(2)) || date.equals(springFestival.plusDays(3)) || date.equals(springFestival.plusDays(4)) || date.equals(springFestival.plusDays(5)) || date.equals(springFestival.plusDays(6)); } // 判断一个日期是否是端午节 private static boolean isDragonBoatFestival(LocalDate date) { int year = date.getYear(); LocalDate dragonBoatFestival = LocalDate.of(year, Month.JUNE, 1) .with(TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY)) .plusWeeks(2); return date.equals(dragonBoatFestival); } // 判断一个日期是否是中秋节 private static boolean isMidAutumnFestival(LocalDate date) { int year = date.getYear(); LocalDate midAutumnFestival = LocalDate.of(year, Month.SEPTEMBER, 1) .with(TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY)) .plusWeeks(2); return date.equals(midAutumnFestival); } } ``` 在上面的代码中,我们使用Java 8提供的日期和时间API来获取当月最后一天,并使用TemporalAdjusters工具类来实现日期调整。如果最后一天是周六或周日,则向前推到最后一个工作日。如果最后一天是节假日,则不断向前推到最后一个非节假日的工作日。最后输出每个月最后一个非节假日的工作日的结果。为了简化示例代码,这里假设元旦、春节、清明节、劳动节、端午节、中秋节和国庆节都是节假日,实际情况可能会有所不同,需要根据实际情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值