📄 c-vm5.html
字号:
<dd><p class="Body"><a name="84646"> </a>To create a new virtual-to-physical mapping, use<b class="routine"><i class="routine"> vmMap</i></b><b>(</b> <b>)</b>; both the physical and virtual address must be determined in advance. The physical memory (which must be page aligned) can be obtained using <b class="routine"><i class="routine">valloc</i></b><b>(</b> <b>)</b>. The easiest way to determine the virtual address is to use <b class="routine"><i class="routine">vmGlobalInfoGet</i></b><b>(</b> <b>)</b> to find a virtual page that is not a global mapping. With this scheme, if multiple mappings are required, a task must keep track of its own private virtual memory pages to guarantee it does not map the same non-global address twice. </p><dd><p class="Body"><a name="84649"> </a>When physical pages are mapped into new sections of the virtual space, the physical page is accessible from two different virtual addresses (a condition known as <i class="term">aliasing</i>): the newly mapped virtual address and the virtual address equal to the physical address in the global virtual memory. This can cause problems for some architectures, because the cache may hold two different values for the same underlying memory location. To avoid this, invalidate the virtual page (using <b class="routine"><i class="routine">vmStateSet</i></b><b>(</b> <b>)</b>) in the global virtual memory. This also ensures that the data is accessible only when the virtual memory context containing the new mapping is current.</p><dd><p class="Body"><a name="84654"> </a><a href="c-vm5.html#84658">Figure 7-2</a> depicts two private virtual memory contexts. The new context (<b class="symbol_lc">pvmc2</b>) maps virtual address 0x6000000 to physical address 0x10000. To prevent access to this address from outside of this virtual context (<b class="symbol_lc">pvmc1</b>), the corresponding physical address (0x10000) must be set to invalid. If access to the memory is made using address 0x10000, a bus error occurs because that address is now invalid.<div class="frame"><h4 class="EntityTitle"><a name="84658"><font face="Helvetica, sans-serif" size="-1" class="sans">Figure 7-2: Mapping Private Virtual Memory</font></a></h4><dl class="margin"><div class="Anchor"><a name="84747"> </a><img class="figure" border="0" src="images/c-vma1.gif"></div></dl></div></p></dl></dl><h4 class="EntityTitle"><a name="84749"><font face="Helvetica, sans-serif" size="-1" class="sans">Example 7-1: Private Virtual Memory Contexts </font></a></h4><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="84750"> </a>In the following code example, private virtual memory contexts are used for allocating memory from a task's private memory partition. The setup routine, <b class="routine"><i class="routine">contextSetup</i></b><b>(</b> <b>)</b>, creates a private virtual memory context that is made current during a context switch. The virtual memory context is stored in the field <b class="symbol_lc">spare1</b> in the task's TCB. Switch hooks are used to save the old context and install the task's private context. Note that the use of switch hooks increases the context switch time. A user-defined memory partition is created using the private virtual memory context. The partition ID is stored in <b class="symbol_lc">spare2</b> in the tasks TCB. Any task wanting a private virtual memory context must call <b class="routine"><i class="routine">contextSetup</i></b><b>(</b> <b>)</b>. A sample task to test the code is included.</p></dl><dl class="margin"><dd><hr class="Line"></dl><dl class="margin"><dd><pre class="Code"><b><a name="84752">/* contextExample.h - header file for vm contexts used by switch hooks */</a></b><dd> <b><a name="84754">#define NUM_PAGES (3)</a></b></pre></dl><dl class="margin"><dd><hr class="Line"></dl><dl class="margin"><dd><pre class="Code"><b><a name="84756">/* context.c - use context switch hooks to make task private context current */ </a></b><dd> <b><a name="84758">#include "vxWorks.h" #include "vmLib.h" #include "semLib.h" #include "taskLib.h" #include "taskHookLib.h" #include "memLib.h" #include "contextExample.h"</a></b><dd> <b><a name="84766">void privContextSwitch (WIND_TCB *pOldTask, WIND_TCB *pNewTask);</a></b><dd> <b><a name="84768">/************************************************************************ * * initContextSetup - install context switch hook * */</a></b><dd> <b><a name="84774">STATUS initContextSetup ( ) { /* Install switch hook */ if (taskSwitchHookAdd ((FUNCPTR) privContextSwitch) == ERROR) return (ERROR);</a></b><dd> <b><a name="84781"> return (OK); }</a></b><dd> <b><a name="84784">/************************************************************************ * * contextSetup - initialize context and create separate memory partition * * Call only once for each task that wants a private context. * * This could be made into a create-hook routine if every task on the * system needs a private context. To use as a create hook, the code for * installing the new virtual memory context should be replaced by simply * saving the new context in spare1 of the task's TCB. */</a></b><dd> <b><a name="84796">STATUS contextSetup (void) { VM_CONTEXT_ID pNewContext; int pageSize; int pageBlkSize; char * pPhysAddr; char * pVirtAddr; UINT8 * globalPgBlkArray; int newMemSize; int index; WIND_TCB * pTcb;</a></b><dd> <b><a name="84808"> /* create context */</a></b><dd> <b><a name="84810"> pNewContext = vmContextCreate();</a></b><dd> <b><a name="85417"> /* get page and page block size */</a></b><dd> <b><a name="85418"> pageSize = vmPageSizeGet (); pageBlkSize = vmPageBlockSizeGet (); newMemSize = pageSize * NUM_PAGES;</a></b><dd> <b><a name="84818"> /* allocate physical memory that is page aligned */</a></b><dd> <b><a name="84820"> if ((pPhysAddr = (char *) valloc (newMemSize)) == NULL) return (ERROR);</a></b><dd> <b><a name="84823"> /* Select virtual address to map. For this example, since only one page * block is used per task, simply use the first address that is not a * global mapping. vmGlobalInfoGet( ) returns a boolean array where each * element corresponds to a block of virtual memory. */</a></b><dd> <b><a name="84829"> globalPgBlkArray = vmGlobalInfoGet(); for (index = 0; globalPgBlkArray[index] == TRUE; index++) ; pVirtAddr = (char *) (index * pageBlkSize);</a></b><dd> <b><a name="84834"> /* map physical memory to new context */</a></b><dd> <b><a name="84836"> if (vmMap (pNewContext, pVirtAddr, pPhysAddr, newMemSize) == ERROR) { free (pPhysAddr); return (ERROR); }</a></b><dd> <b><a name="84842"> /* * Set state in global virtual memory to be invalid - any access to * this memory must be done through new context. */</a></b><dd> <b><a name="84847"> if (vmStateSet(pNewContext, pPhysAddr, newMemSize, VM_STATE_MASK_VALID, VM_STATE_VALID_NOT) == ERROR) return (ERROR);</a></b><dd> <b><a name="84851"> /* get tasks TCB */</a></b><dd> <b><a name="84853"> pTcb = taskTcb (taskIdSelf());</a></b><dd> <b><a name="84855"> /* change virtual memory contexts */</a></b><dd> <b><a name="84857"> /* * Stash the current vm context in the spare TCB field -- the switch * hook will install this when this task gets swapped out. */</a></b><dd> <b><a name="84862"> pTcb->spare1 = (int) vmCurrentGet();</a></b><dd> <b><a name="84864"> /* install new tasks context */</a></b><dd> <b><a name="84866"> vmCurrentSet (pNewContext);</a></b><dd> <b><a name="84868"> /* create new memory partition and store id in task's TCB */</a></b><dd> <b><a name="84870"> if ((pTcb->spare2 = (int) memPartCreate (pVirtAddr,newMemSize)) == NULL) return (ERROR);</a></b><dd> <b><a name="85507"> return (OK); }</a></b><dd> <b><a name="85509">/******************************************************************* * * privContextSwitch - routine to be executed on a context switch * * If old task had private context, save it. If new task has private * context, install it. */</a></b><dd> <b><a name="84884">void privContextSwitch ( WIND_TCB *pOldTcb, WIND_TCB *pNewTcb )</a></b><dd> <b><a name="84890"> { VM_CONTEXT_ID pContext = NULL; /* If previous task had private context, save it--reset previous context. */</a></b><dd> <b><a name="84895"> if (pOldTcb->spare1) { pContext = (VM_CONTEXT_ID) pOldTcb->spare1; pOldTcb->spare1 = (int) vmCurrentGet ();</a></b><dd> <b><a name="84900"> /* restore old context */</a></b><dd> <b><a name="84902"> vmCurrentSet (pContext); }</a></b><dd> <b><a name="84905"> /* * If next task has private context, map new context and save previous * context in task's TCB. */ </a></b><dd> <b><a name="85564"> if (pNewTcb->spare1) { pContext = (VM_CONTEXT_ID) pNewTcb->spare1; pNewTcb->spare1 = (int) vmCurrentGet();</a></b><dd> <b><a name="85566"> /* install new tasks context */</a></b><dd> <b><a name="84917"> vmCurrentSet (pContext); } }</a></b></pre></dl><dl class="margin"><dd><hr class="Line"></dl><dl class="margin"><dd><pre class="Code"><b><a name="84922">/* taskExample.h - header file for testing VM contexts used by switch hook */ </a></b><dd> <b><a name="84924">/* This code is used by the sample task. */</a></b><dd> <b><a name="84926">#define MAX (10000000)</a></b><dd> <b><a name="84928">typedef struct myStuff { int stuff; int myStuff; } MY_DATA;</a></b></pre></dl><dl class="margin"><dd><hr class="Line"></dl><dl class="margin"><dd><pre class="Code"><b><a name="84934">/* testTask.c - task code to test switch hooks */</a></b><dd> <b><a name="84936">#include "vxWorks.h" #include "memLib.h" #include "taskLib.h" #include "stdio.h" #include "vmLib.h" #include "taskExample.h"</a></b><dd> <b><a name="84943">IMPORT char *string = "test\n";</a></b><dd> <b><a name="84945">MY_DATA *pMem;</a></b><dd> <b><a name="84947">/************************************************************************ * * testTask - allocate private memory and use it * * Loop forever, modifying memory and printing out a global string. Use this * in conjunction with testing from the shell. Since pMem points to private * memory, the shell should generate a bus error when it tries to read it. * For example: * -> sp testTask * -> d pMem */</a></b><dd> <b><a name="84959">STATUS testTask (void) { int val; WIND_TCB *myTcb;</a></b><dd> <b><a name="84964"> /* install private context */</a></b><dd> <b><a name="84966"> if (contextSetup () == ERROR) return (ERROR);</a></b><dd> <b><a name="84969"> /* get TCB */</a></b><dd> <b><a name="84971"> myTcb = taskTcb (taskIdSelf ());</a></b><dd> <b><a name="84973"> /* allocate private memory */</a></b><dd> <b><a name="84975"> if ((pMem = (MY_DATA *) memPartAlloc((PART_ID) myTcb->spare2, sizeof (MY_DATA))) == NULL) return (ERROR);</a></b><dd> <b><a name="84979"> /* * Forever, modify data in private memory and display string in * global memory. */</a></b><dd> <b><a name="84984"> FOREVER { for (val = 0; val <= MAX; val++) { /* modify structure */</a></b><dd> <b><a name="84990"> pMem->stuff = val; pMem->myStuff = val / 2;</a></b><dd>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -