ÒýÓÃ:±¾ÎĽö×öѧϰ²Î¿¼ÓÃ
¡¡¡¡Ò»¡¢ Ç°ÑÔ
¡¡¡¡·ÇÒ»ÖÂÐÔÄÚ´æ·ÃÎÊ£¨Non-Uniform Memory Access£©½á¹¹ÊÇ·Ö²¼Ê½¹²ÏíÄڴ棨Distributed Shared Memory£©Ìåϵ½á¹¹µÄÖ÷Òª·ÖÖ§£¬Ëüͨ¹ý½áºÏ·Ö²¼Ê½ÄÚ´æ¼¼ÊõºÍµ¥Ò»ÏµÍ³Ó³Ïñ£¨SSI£©¼¼Êõ£¬ÊµÏÖÁËSMP ϵͳµÄÒ×±à³ÌÐÔºÍ MPPϵͳµÄÒ×À©Õ¹ÐÔµÄÕÛÖУ¬ÒѳÉΪµ±½ñ¸ßÐÔÄÜ·þÎñÆ÷µÄÖ÷Á÷Ìåϵ½á¹¹Ö®Ò»¡£Ä¿Ç°¹úÍâÖøÃûµÄ·þÎñÆ÷³§É̶¼ÏȺóÍƳöÁË»ùÓÚ NUMA ¼Ü¹¹µÄ¸ßÐÔÄÜ·þÎñÆ÷£¬ÈçHPµÄSuperdome¡¢SGI µÄ Altix 3000¡¢Origin 3000¡¢IBM µÄ x440¡¢NEC µÄ TX7¡¢AMD µÄOpteron µÈ¡£
¡¡¡¡
¡¡¡¡Ëæ×ÅNUMA¼Ü¹¹µÄ¸ßÐÔÄÜ·þÎñÆ÷±»Öð½¥Íƹ㣬ϵͳÈí¼þÕë¶ÔÕâÖÖ·Ö²¼Ê½¹²ÏíÄÚ´æ¼Ü¹¹µÄÌص㣬ÔÚµ÷¶ÈÆ÷¡¢´æ´¢¹ÜÀíºÍÓû§¼¶½Ó¿ÚµÈ·½Ãæ½øÐÐÁË´óÁ¿µÄÓÅ»¯¹¤×÷¡£ÀýÈ磬SGIµÄOrigin 3000 ccNUMAϵͳÔÚÐí¶àÁìÓòµÃµ½Á˹㷺ӦÓã¬ÊǸö·Ç³£³É¹¦µÄϵͳ£¬ÎªÁËÓÅ»¯Origin 3000µÄÐÔÄÜ£¬SGIµÄIRIX²Ù×÷ϵͳÔÚÆäÉÏʵÏÖÁËCpuMemSets£¬Í¨¹ý½«Ó¦ÓÃÓë´¦ÀíÆ÷ºÍÄÚ´æµÄ°ó¶¨£¬³ä·Ö·¢»ÓNUMAϵͳ±¾µØ·Ã´æµÄÓÅÊÆ¡£LinuxÉçÇøÔÚ×Ô¼ºµÄNUMAÏîÄ¿ÖÐҲʵÏÖÁËCpuMemSets£¬²¢ÇÒÔÚSGIµÄAltix 3000µÄ·þÎñÆ÷Öеõ½Êµ¼ÊÓ¦Óá£
¡¡¡¡
¡¡¡¡±¾ÎĽ«ÒÔ SGI µÄ ProPack v2.2 ΪÑо¿¶ÔÏ󣬷ÖÎö CpuMemSets ÔÚLinux-2.4.20 ÖеľßÌåʵÏÖ¡£CpuMemSets ÊÇ SGI ½øÐеÄÒ»¸ö¿ª·ÅÔ´ÂëÏîÄ¿£¬ÓÉÕë¶Ô Linux2.4 Äں˵IJ¹¶¡¡¢Óû§¿â¡¢python Ä£¿éºÍ runon µÈÃüÁî¹²ËIJ¿·Ö×é³É£¬ÒÔʵÏÖ´¦ÀíÆ÷ºÍÄÚ´æ¿éµÄ·ÖÇøΪĿ±ê£¬¿ØÖÆϵͳ×ÊÔ´£¨´¦ÀíÆ÷¡¢ÄÚ´æ¿é£©ÃæÏòÄںˡ¢ÈÎÎñÒÔ¼°ÐéÄâ´æ´¢ÇøµÄ·ÖÅ䣬Ϊ dplace¡¢RunOn µÈ NUMA ¹¤¾ßÌṩ֧³Ö£¬×îÖÕÓÅ»¯ Linux ϵͳµÄ NUMA ÐÔÄÜ¡£
¡¡¡¡
¡¡¡¡¶þ¡¢ Ïà¹Ø¹¤×÷
¡¡¡¡·ÖÇø¼¼Êõ£¨Partition£©×î³õ³öÏÖÔÚ´óÐÍ»ú£¨MainFrame£©ÉÏ£¬Èç½ñ±»¹ã·ºÓ¦Óõ½·þÎñÆ÷ÁìÓò£¬Ö§³ÖÔÚµ¥¸ö·þÎñÆ÷ÉÏÔËÐÐÒ»¸ö²Ù×÷ϵͳµÄ¶à¸öʵÀý»òÕ߶à¸ö²Ù×÷ϵͳµÄ¶à¸öʵÀý£¬Ö÷ÒªÌصãÊÇ"»úÆ÷¶ÀÁ¢¡¢ÆÁÕÏ¿É¿¿¡¢µ¥µã¹ÜÀí"¡£ÔÚ·ÖÇø¼¼ÊõÖ§³ÖÏ£¬µ±Ç°¶ą̀·þÎñÆ÷ÔËÐеĶà¸ö²Ù×÷ϵͳ¾Í¿ÉÒÔÔÚͬһµØµãµÄһ̨·þÎñÆ÷ÉÏͬʱÔËÐУ¬ÓÅÓÚÔÚÒ»¸ö×éÖ¯ÖÐËÄ´¦·ÖÉ¢Óöà¸ö·þÎñÆ÷À´Ö§³Ö²»Í¬µÄ²Ù×÷ϵͳ£¬´Ó¶øÓÐЧµØʵÏÖÁË·þÎñÆ÷ÕûºÏ¡£Ö§³Ö·ÖÇø¼¼ÊõµÄ·þÎñÆ÷¿ÉÒÔµ±×÷Ó¦Ó÷þÎñÆ÷£¬ÔËÐÐWindowsƽ̨¹©Êг¡²¿ÃÅʹÓã»Í¬Ê±»¹¿ÉÒÔÔËÐÐLinuxϵͳ¹©¹¤³Ì²¿ÃÅʹÓ᣻¹¿ÉÒÔÔÚ´ó¶àÊýÓû§ÔËÐÐWindows 2000 Advanced ServerϵͳµÄͬʱ£¬ÔÚÁíÒ»¸ö·ÖÇøÖÐΪ·¢Õ¹×é²âÊÔÆäËü²Ù×÷ϵͳ£»»òÕßËùÓнڵ㶼ӦÓÃÔÚÒ»¸ö²Ù×÷ϵͳ»·¾³Ï¡£¸÷ÖÖ·ÖÇøʵÏÖ¼¼ÊõµÄÖ÷Òª²î±ðÌåÏÖÔÚ·ÖÇø¹ÊÕϸôÀëÊֶΣ¨Ó²¼þ»òÈí¼þ£©¡¢·ÖÇø×ÊÔ´Á£¶È¡¢·ÖÇø×ÊÔ´Áé»îÐÔÒÔ¡¢ÐéÄâ·ÖÇø×ÊÔ´ÒÔ¼°¶Ô¶¯Ì¬·ÖÇøÖع¹µÄÖ§³ÖµÈ·½Ãæ¡£µäÐ͵ÄÓÐIBMµÄLPARºÍDLAPAR£¨AIX 5L 5.1£©¡¢HPµÄnPartitionsºÍvPartitions£¨HP-UX 11i£©¡¢SUNµÄDynamic Domains£¨Solaris 8£©¡¢ÒÔ¼°CompaqµÄAlpha Servers£¨Tru64 Unix 5.1£©¡£µ«ÊÇ£¬Õë¶ÔNUMAϵͳ²ÉÓõķÖÇø¼¼ÊõÓëNUMAϵͳ±¾Éí¾ßÓеĵ¥ÏµÍ³Ó³ÏñÓÅÊÆÊÇì¶ÜµÄ¡£
¡¡¡¡
¡¡¡¡´ÓÓû§µÄ½Ç¶ÈÀ´¿´£¬NUMAϵͳÌṩÁ˶Ա¾µØÖ÷´æºÍÔ¶³ÌÖ÷´æ·ÃÎʵÄ͸Ã÷ÐÔ£»µ«ÊÇ£¬´ÓÐÔÄܵĽǶÈÀ´¿´£¬ÓÉÓڴ洢ģ¿éÎïÀíÉÏ·Ö²¼ÔÚ²»Í¬µÄ½ÚµãÒýÆðµÄ´æ´¢·ÃÎÊÑÓ³Ù²»Ò»ÖÂÏÖÏ󣬶ÔϵͳµÄÐÔÄÜÒ²´øÀ´Á˽ϴóµÄÓ°Ïì¡£ÔÚÕâÀàϵͳÖУ¬Ò»¸ö½Úµã¶ÔÔ¶³Ì½Úµã´æ´¢·ÃÎʵÄÑÓ³Ùͨ³£±È±¾µØ·ÃÎÊÑÓ³Ù¸ß1µ½2¸öÊýÁ¿¼¶¡£Ò³Ç¨ÒÆÓëÒ³¸´ÖÆÊǶÔÊý¾Ý½øÐж¯Ì¬¾Ö²¿ÐÔÓÅ»¯µÄÖ÷Òª·½·¨Ö®Ò»¡£ÆäʵÖÊÊÇÒ»ÖÖÔ¤²â¼¼Êõ£¬¸ù¾ÝÊÕ¼¯µ½µÄÐÅÏ¢Ô¤²â½«À´¶ÔÒ³ÃæµÄ·ÃÎÊÇé¿ö£¬È»ºó×÷³öǨÒÆ»ò¸´ÖÆÒ³ÃæµÄ¾ö²ß¡£²ÉÓÃÊʵ±µÄÒ³¸´ÖÆÓëҳǨÒƲßÂÔ¿ÉÒÔ¼õСcacheÈÝÁ¿ºÍ³åͻʧЧ£¬Æ½ºâÔ¶³ÌºÍ±¾µØ·ÃÎÊÑӳٵIJ»Ò»Ö£¬´ïµ½ÓÅ»¯NUMAϵͳÐÔÄܵÄÄ¿µÄ¡£µ«ÊÇÏÖÓеÄҳǨÒÆÓëÒ³¸´ÖƲßÂԴ󶼹ý·ÖÒÀÀµÓÚÌåϵ½á¹¹ºÍÌØÊâµÄÓ²¼þÖ§³Ö£¬¿ªÏú±È½Ï´ó£¬Í¨ÓÃÐÔÒ²²»ºÃ¡£
¡¡¡¡
¡¡¡¡ÔÚNUMA½á¹¹µÄ¶à´¦ÀíÆ÷ϵͳÖУ¬Ò»¸öÈÎÎñ¿ÉÒÔÔÚÈκÎÒ»¸ö´¦ÀíÆ÷ÉÏÔËÐУ¬È»¶øÈÎÎñÔÚ¸÷ÖÖÇé¿öµÄÖ´ÐлᱻÖжϣ»±»ÖжϵÄÈÎÎñÔÚ»Ö¸´Ö´ÐеÄʱºò£¬Èç¹ûÑ¡Ôñ»Ö¸´ÔÚÁíÍâÒ»¸ö´¦ÀíÆ÷ÉÏÖ´ÐУ¬¾Í»áµ¼ÖÂËüʧȥÔÓеĴ¦ÀíÆ÷cacheÊý¾Ý¡£ÎÒÃÇÖªµÀ£¬·ÃÎÊcacheÊý¾ÝÖ»ÐèÒª¼¸¸öÄÉÃ룬¶ø·ÃÎÊÖ÷´æÐèÒª´óÔ¼50ÄÉÃë¡£Õâʱ´¦ÀíÆ÷ÔËÐеÄËٶȴ¦ÔÚ·ÃÎÊÖ÷´æµÄ¼¶±ðÉÏ£¬Ö±µ½ÈÎÎñÔËÐÐÁË×ã¹»µÄʱ¼ä£¬ÈÎÎñÔËÐÐËùÐèÒªµÄÊý¾ÝÖØгäÂú¸Ã´¦ÀíÆ÷µÄcacheΪֹ¡£Îª½â¾öÕâ¸öÎÊÌ⣬ϵͳ¿ÉÒÔ²ÉÓô¦ÀíÆ÷Ç×½üµ÷¶È²ßÂÔµ÷¶Èÿ¸ö½ÚµãÉϵÄÈÎÎñ£ºÏµÍ³¼Ç¼ÏÂ×îºóÖ´ÐÐÕâ¸öÈÎÎñµÄ´¦ÀíÆ÷²¢Î¬³ÖÕâÖÖ¹Øϵ£¬ÔÚ»Ö¸´Ö´Ðб»ÖжϵÄÈÎÎñʱ£¬¾¡Á¿»Ö¸´ÔÚ×îºóÖ´ÐÐÕâ¸öÈÎÎñµÄ´¦ÀíÆ÷ÉÏÖ´ÐС£µ«ÊÇ£¬ÓÉÓÚÓ¦ÓóÌÐòµÄÌصã¸÷Óв»Í¬£¬¶øÇÒ¹¤×÷¼¯¾ßÓж¯Ì¬ÊôÐÔ£¬´¦ÀíÆ÷Ç×½üµ÷¶ÈµÄ×÷ÓÃÊÇÓÐÏ޵ġ£
¡¡¡¡
¡¡¡¡Óû§ÊÇϵͳµÄʹÓÃÕߣ¬Ò²ÊÇÐÔÄܵÄÆÀÅÐÕߣ¬ËûÃÇ×îÇå³þÓ¦ÓöÔϵͳµÄÐèÇóºÍÆÀ¼ÛÖ¸±ê¡£ÔÚÒ»¸ö´óµÄNUMAϵͳÖУ¬Óû§ÍùÍùÏ£Íû¿ØÖÆÒ»²¿·Ö´¦ÀíÆ÷ºÍÄÚ´æ¸øijЩÌØÊâµÄÓ¦Óá£CpuMemSetsÔÊÐíÓû§¸ü¼ÓÁé»îµÄ¿ØÖÆ£¨Ëü¿ÉÒÔÖصþ¡¢»®·ÖϵͳµÄ´¦ÀíÆ÷ºÍÄڴ棩£¬ÔÊÐí¶à¸ö½ø³Ì½«ÏµÍ³¿´³ÉÒ»¸öµ¥ÏµÍ³Ó³Ïñ£¬²¢ÇÒ²»ÐèÒªÖØÆôϵͳ£¬±£ÕÏijЩ´¦ÀíÆ÷ºÍÄÚ´æ×ÊÔ´ÔÚ²»Í¬µÄʱ¼ä·ÖÅä¸øÖ¸¶¨µÄÓ¦Óã»Ò²ÊǶԷÖÇø¼¼Êõ¡¢Ò³Ç¨ÒƺÍÇ×½üµ÷¶È²ßÂÔµÄÓÐÒæ²¹³ä¡£
¡¡¡¡
¡¡¡¡Èý¡¢ ϵͳʵÏÖ
¡¡¡¡ÔÚ½éÉÜCpuMemSetsÔÚLinux-2.4.20ÖеľßÌåʵÏÖ֮ǰ£¬ÎÒÃÇÊ×ÏÈ˵Ã÷CpuMemSetsÉæ¼°µÄ¼¸¸ö»ù±¾¸ÅÄ°üÀ¨£º
¡¡¡¡
¡¡¡¡´¦ÀíÆ÷£ºÖ¸³ÐÔØÈÎÎñµ÷¶ÈµÄÎïÀí´¦ÀíÆ÷£¬µ«ÊDz»°üÀ¨DMAÉ豸¡¢ÏòÁ¿´¦ÀíÆ÷µÈרÓô¦ÀíÆ÷£»
¡¡¡¡ÄÚ´æ¿é£ºÔÚSMP¡¢UPϵͳÖУ¬ËùÓеÄÄÚ´æ¿éÓëËùÓд¦ÀíÆ÷µÄ¾àÀëÏàµÈ£¬Òò´Ë²»´æÔÚ²î±ð£»µ«ÊÇÔÚNUMAϵͳÖУ¬¿ÉÒÔ°´ÕÕÓë´¦ÀíÆ÷µÄ¾àÀë¶ÔÄÚ´æ¿é»®·ÖµÈ¼ÛÀà¡£´ËÍ⣬CpuMemSets²»¿¼ÂǾßÓÐËٶȲîÒìµÄÌØÊâ´æ´¢Æ÷£¬ÈçÊäÈëÊä³öÉ豸»º´æ¡¢Ö¡»º´æµÈ¡£
¡¡¡¡
¡¡¡¡ÈÎÎñ£ºÒ»¸öÈÎÎñ£¬ÔÚÈÎһʱ¿Ì£¬»òÕߵȴýʼþ¡¢×ÊÔ´£¬»òÕß±»Öжϣ¬»òÕßÔÚ´¦ÀíÆ÷ÉÏÔËÐС£
¡¡¡¡ÐéÄâ´æ´¢Çø£ºÄÚºËΪÿ¸öÈÎÎñά»¤µÄ¶à¸öÐéÄâµØÖ·ÇøÓò£¬¿ÉΪ¶à¸öÈÎÎñ¹²Ïí¡£Î»ÓÚÐéÄâ´æ´¢ÇøÄÚµÄÒ³£¬»òÕßûÓзÖÅ䣬»òÕßÒÑ·ÖÅ䵫±»»»³ö£¬»òÕßÒÑ·ÖÅäÇÒÔÚÄÚ´æÖС£¿ÉÒÔÖ¸¶¨ÔÊÐí·ÖÅä¸øij¸öÐéÄâ´æ´¢ÇøµÄÄÚ´æ¿éÒÔ¼°·ÖÅä˳Ðò¡£
¡¡¡¡
¡¡¡¡CpuMemSetsΪLinuxÌṩÁ˽«ÏµÍ³·þÎñºÍÓ¦Óðó¶¨ÔÚÖ¸¶¨µÄ´¦ÀíÆ÷ÉϽøÐе÷¶È¡¢ÔÚÖ¸¶¨µÄ½áµãÉÏ·ÖÅäÄÚ´æµÄ»úÖÆ¡£CpuMemSetsÔÚÒÑÓеÄLinuxµ÷¶ÈºÍÄÚ´æ·ÖÅä´úÂë»ù´¡ÉÏÔö¼ÓÁËcpumemmap£¨cmm£©ºÍcpumemset£¨cms£©Á½²ã½á¹¹£¬µ×²ãµÄcpumemmap²ãÌṩһ¸ö¼òµ¥µÄÓ³Éä¶Ô£¬ÊµÏÖϵͳµÄ´¦ÀíÆ÷ºÅÓëÓ¦ÓõĴ¦ÀíÆ÷ºÅ¡¢ÏµÍ³µÄÄÚ´æ¿éºÅÓëÓ¦ÓõÄÄÚ´æ¿éºÅµÄÓ³Éä¡£ÕâÖÖÓ³Éä²»Ò»¶¨Êǵ¥É䣬һ¸öϵͳºÅ¿ÉÒÔ¶ÔÓ¦¶à¸öÓ¦Óúš£ÉϲãµÄcpumemset²ã¸ºÔð˵Ã÷ÔÊÐí°ÑÈÎÎñµ÷¶Èµ½ÄÄЩӦÓô¦ÀíÆ÷ºÅËù¶ÔÓ¦µÄ´¦ÀíÆ÷ÉÏÔËÐС¢¿ÉÒÔ´ÓÄÄЩӦÓÃÄÚ´æ¿éºÅËù¶ÔÓ¦µÄÄÚ´æ¿éÖÐΪÏàÓ¦µÄÄں˻òÐéÄâ´æ´¢Çø·ÖÅäÄÚ´æÒ³£¬Ò²¾ÍÊÇ˵£¬Ö¸¶¨¿É¹©Äںˡ¢ÈÎÎñ¡¢ÐéÄâ´æ´¢ÇøʹÓõÄ×ÊÔ´¼¯ºÏ¡£ÔÚÕâÖÖÁ½²ã½á¹¹ÖУ¬×ÊÔ´µÄϵͳºÅ¹©ÄÚºËÖ´Ðе÷¶ÈºÍÄÚ´æ·ÖÅäʱʹÓ㻶ø×ÊÔ´µÄÓ¦ÓúŹ©Óû§½ø³ÌÖ¸¶¨±¾Ó¦ÓõÄ×ÊÔ´¼¯ºÏʱʹÓá£ÏµÍ³ºÅÔÚÆô¶¯ÆÚ¼äȫϵͳ·¶Î§ÄÚÓÐЧ£¬¶øÓ¦ÓúŽö½öÏà¶ÔÓÚ¹²Ïíͬһ¸öcmmµÄËùÓÐÓû§½ø³ÌÓÐЧ¡£¶øÇÒ£¬ÓÉÓÚ¸ºÔØƽºâºÍÈȲå°ÎÒý·¢µÄ×ÊÔ´ÎïÀí±àºÅµÄ±ä»¯¶ÔÓ¦ÓúÅÊDz»¿É¼ûµÄ¡£
¡¡¡¡
¡¡¡¡LinuxµÄ½ø³Ìµ÷¶ÈºÍÄÚ´æ·ÖÅäÔÚ±£³ÖÏÖÓдúÂëÕý³£ÔËתµÄ»ù´¡ÉÏ£¬Ìí¼ÓÁ˶ÔCpuMemSetsµÄÖ§³Ö£¬Ê¹ÓÃ"ϵͳ´¦ÀíÆ÷ºÅ"ºÍ"ϵͳÄÚ´æ¿éºÅ"ÒÔ¼°ÆäËûÊý¾Ý½á¹¹Èçcpus_allowedºÍmems_allowedµÈʵÏÖ×ÊÔ´µÄ·ÖÇø¡£´ËÍ⣬CpuMemSetsµÄAPIÌṩÁ˶Ôcpusets¡¢dplace¡¢runon¡¢psets¡¢MPI¡¢OpenMP¡¢nodesetsµÄÖ§³Ö£¬²¢ÇÒÌṩ/proc½Ó¿ÚÒÔÏÔʾcmmºÍ cmsµÄ½á¹¹¡¢ÉèÖÃÒÔ¼°ÓëÈÎÎñ¡¢ÐéÄâ´æ´¢Çø¡¢Äں˵ÄÁ¬½Ó¹Øϵ¡¢ÏµÍ³×ÊÔ´ºÅºÍÓ¦ÓÃ×ÊÔ´ºÅµÈÐÅÏ¢¡£ÏÂÃæÎÒÃÇ·Ö±ð¶ÔcpumemmapºÍcpumemset¡¢½ø³Ìµ÷¶ÈºÍÄÚ´æ·ÖÅä¡¢ÒÔ¼°APIÕâÈý¸ö²¿·Ö½øÐÐÏêϸ·ÖÎö£º
¡¡¡¡
¡¡¡¡3.1 cmm&cms
¡¡¡¡3.1.1 Êý¾Ý½á¹¹
¡¡¡¡
¡¡¡¡cpumemmapºÍcpumemsetµÄÊý¾Ý½á¹¹ÈçÏÂËùʾ£¬¾ßÌ嶨ÒåÔÚinclude/linux/cpumemset.hÖС£CpumemmapÖеÄscpusºÍsmemsÓò·Ö±ðÖ¸ÏòÒ»×éϵͳ´¦ÀíÆ÷ºÅºÍÒ»×éϵͳÄÚ´æ¿éºÅ£¬ÊµÏÖÓ¦ÓõÄ×ÊÔ´ºÅ£¨Êý×éϱ꣩ÓëϵͳµÄ×ÊÔ´ºÅ£¨Êý×éÔªËØÖµ£©µÄÓ³Éä¡£CpumemsetÖеÄacpusÓòÖ¸ÏòÒ»×éÓ¦Óô¦ÀíÆ÷ºÅ£¬¶øamemsÓòÖ¸ÏòÒ»×écms_memory_list_tÀàÐ͵ÄÄÚ´æ¿éÁÐ±í¡£Ã¿¸öÄÚ´æ¿éÁбíÃèÊöÁËÒ»×éÓ¦ÓÃÄÚ´æ¿éºÅ£¨mems£©ÒÔ¼°ÏíÓиÃÁбíµÄÒ»×éÓ¦Óô¦ÀíÆ÷ºÅ£¨cpus£©¡£ÄÚ´æ¿é·ÖÅä²ßÂÔÓÉcpumemsetÖеÄpolicyÓò¾ö¶¨£¬È±Ê¡Ê¹Óñ¾µØÓÅÏÈ·½Ê½¡£Cpumemsetͨ¹ýcmmÓòÓëÏàÓ¦µÄcpumemmap½¨Á¢¹ØÁª¡£Á½¸öÊý¾Ý½á¹¹ÖеÄcounterÓòµÄ×÷Óý«ÔÚºóÎĽéÉÜ¡£
¡¡¡¡
¡¡¡¡¡¾include/linux/cpumemset.h¡¿
¡¡¡¡84 typedef struct cpumemmap {
¡¡¡¡85¡¡¡¡¡¡¡¡ int nr_cpus;¡¡¡¡¡¡¡¡¡¡¡¡¡¡/* number of cpus in map */
¡¡¡¡86¡¡¡¡¡¡¡¡ int nr_mems;¡¡¡¡¡¡¡¡¡¡¡¡¡¡/* number of mems in map */
¡¡¡¡87¡¡¡¡¡¡¡¡ cms_scpu_t *cpus;¡¡¡¡¡¡ /* array maps application to system cpu num */
¡¡¡¡88¡¡¡¡¡¡¡¡ cms_smem_t *mems;¡¡¡¡¡¡ /* array maps application to system mem num */
¡¡¡¡89¡¡¡¡¡¡¡¡ atomic_t counter;¡¡¡¡¡¡ /* reference counter */
¡¡¡¡90¡¡¡¡¡¡ } cpumemmap_t;
¡¡¡¡
¡¡¡¡92 typedef struct cpumemset {
¡¡¡¡93¡¡¡¡¡¡¡¡ cms_setpol_t policy;¡¡¡¡/* CMS_* policy flag £ºMemory allocation policy */
¡¡¡¡94¡¡¡¡¡¡¡¡ int nr_cpus;¡¡¡¡¡¡¡¡¡¡¡¡¡¡ /* Number of cpus in this CpuMemSet */
¡¡¡¡95¡¡¡¡¡¡¡¡ int nr_mems;¡¡¡¡¡¡¡¡¡¡¡¡¡¡ /* Number of Memory Lists in this CpuMemSet */
¡¡¡¡96¡¡¡¡¡¡¡¡ cms_acpu_t *cpus;¡¡¡¡¡¡¡¡/* The 'nr_cpus' app cpu nums in this set */
¡¡¡¡97¡¡¡¡¡¡¡¡ cms_memory_list_t *mems;¡¡¡¡¡¡¡¡ /* Array 'nr_mems' Memory Lists */
¡¡¡¡98¡¡¡¡¡¡¡¡ unsigned long mems_allowed;¡¡¡¡ /* memory_allowed vector used by vmas */
¡¡¡¡99¡¡¡¡¡¡¡¡ cpumemmap_t *cmm;¡¡¡¡¡¡¡¡/* associated cpumemmap */
¡¡¡¡100¡¡¡¡¡¡¡¡atomic_t counter;¡¡¡¡¡¡¡¡/* reference counter */
¡¡¡¡101¡¡} cpumemset_t;
¡¡¡¡
¡¡¡¡76¡¡¡¡ typedef struct cms_memory_list {
¡¡¡¡77¡¡¡¡¡¡¡¡ int nr_cpus;¡¡¡¡¡¡¡¡¡¡¡¡/* Number of cpu's sharing this memory list */
¡¡¡¡78¡¡¡¡¡¡¡¡ int nr_mems;¡¡¡¡¡¡¡¡¡¡¡¡/* Number of memory nodes in this list */
¡¡¡¡79¡¡¡¡¡¡¡¡ cms_acpu_t *cpus;¡¡¡¡¡¡ /* Array of cpu's sharing this memory list */
¡¡¡¡80¡¡¡¡¡¡¡¡ cms_amem_t *mems;¡¡¡¡¡¡ /* Array of 'nr_mems' memory nodes */
¡¡¡¡81 } cms_memory_list_t;
¡¡¡¡
¡¡¡¡ÒÔÒ»¸ö°üº¬Ëĸö½ÚµãµÄNUMAϵͳΪÀý¼òµ¥ËµÃ÷ÉÏÊöÊý¾Ý½á¹¹µÄʹÓ᣼ÙÉèÿ¸ö½ÚµãÓÉËĸö½ÚµãºÍÒ»¸öÄÚ´æ¿é×é³É£¬16¸ö´¦ÀíÆ÷µÄϵͳºÅÒÀ´ÎÊÇ£ºc0£¨0£©¡¢c1£¨1£©¡¢¡ ¡¡¢c15£¨15£©£¬4¸öÄÚ´æ¿éµÄϵͳºÅÒÀ´ÎÊÇmb0£¨0£©¡¢mb1£¨1£©¡¢mb2£¨2£©¡¢mb3£¨3£©¡£¹¹ÔìÒ»¸öÖ»°üº¬µÚ2ºÍµÚ3½ÚµãµÄ´¦ÀíÆ÷ºÍÄÚ´æ¿écpumemmap£¬²¢ÇÒ°Ñij¸öÓ¦Óðó¶¨ÔÚÆæÊýºÅµÄ´¦ÀíÆ÷ÉÏ£¬Í¬Ê±ÒÔ±¾µØÓÅÏȵķ½Ê½·ÖÅäÄÚ´æ¿é¡£Êý¾Ý½á¹¹Èçͼ1Ëùʾ£º
¡¡¡¡
¡¡
¡¡¡¡3.1.2 »ù±¾²Ù×÷
¡¡¡¡
¡¡¡¡¶à¸öÈÎÎñ¿ÉÒÔͬʱ¶ÔÖ¸¶¨µÄcms&cmmÖ´ÐзÃÎÊ¡¢¹Ò½Ó¡¢ÊÍ·Å»òÌæ»»µÄ²Ù×÷¡£ÕâЩ²Ù×÷¶¼ÊÇͨ¹ýÏÂÁÐÀý³ÌÖ´ÐУº
¡¡¡¡
¡¡
¡¡¡¡¾ä±ú½á¹¹¶¨ÒåÈçÏ£º
¡¡¡¡
¡¡¡¡¡¾include/linux/cpumemset.h¡¿
¡¡¡¡417 typedef struct cmshandle {
¡¡¡¡418¡¡¡¡¡¡¡¡ cpumemset_t *set;
¡¡¡¡419¡¡¡¡¡¡¡¡ cpumemmap_t *map;
¡¡¡¡420¡¡¡¡¡¡¡¡ int error;
¡¡¡¡421 } cmshandle_t;
¡¡¡¡
¡¡¡¡ÉÏÊöÀý³Ìͨ¹ýËø»úÖÆÒÔ¼°¶Ôcmm&cmsÖеÄÒýÓüÆÊýcounterµÄ¹ÜÀí£¬±£Ö¤Á˶ÔCpuMemSets½øÐв¢ÐвÙ×÷µÄÍêÕûÐÔ¡£Ã¿¸öcmsÖеÄcounter¼Ç¼×Å£ºÊ¹ÓÃÕßµÄÒýÓüÆÊý£¨Ö¸ÏòÕâ¸öcmsµÄÈÎÎñ¡¢ÐéÄâ´æ´¢Çø¡¢ÄÚºË×ÜÊý£©ºÍ¾ä±úµÄÒýÓüÆÊý£¨ÁÙʱָÏòÕâ¸öcmsµÄ¾ä±úµÄ×ÜÊý£©¡£Ã¿¸öcmmÖеÄcounter¼Ç¼×Å£ºcmsµÄÒýÓüÆÊý£¨Ö¸ÏòÕâ¸öcmmµÄcms×ÜÊý£©ºÍ¾ä±úµÄÒýÓüÆÊý£¨ÁÙʱָÏòÕâ¸öcmmµÄ¾ä±úµÄ×ÜÊý£©¡£
¡¡¡¡
¡¡¡¡Ìæ»»CpuMemSetsµÄ²Ù×÷·ÖΪÏÂÁÐÈý¸ö²½Ö裺
¡¡¡¡
¡¡¡¡1. µ÷ÓúÏÊʵÄcmsGetHandle*()°²È«µÄ»ñµÃcmsºÍcmmµÄ¾ä±ú£»
¡¡¡¡
¡¡¡¡2. ¹¹ÔìеÄcmsºÍcmm£»
¡¡¡¡
¡¡¡¡3. µ÷ÓúÏÊʵÄcmsExchange*()°²È«µÄ¸ü»»ÉÏÊöµÄоÉcmsºÍcmm¡£
¡¡¡¡
¡¡¡¡·ÃÎÊÈÎÎñ»òÐéÄâ´æ´¢ÇøµÄcmsºÍcmmµÄ²Ù×÷·ÖΪÏÂÁÐÈý¸ö²½Ö裺
¡¡¡¡
¡¡¡¡1. µ÷ÓúÏÊʵÄcmsGetHandle*()°²È«µÄ»ñµÃcmsºÍcmmµÄ¾ä±ú£»
¡¡¡¡
¡¡¡¡2. µ÷ÓÃcmsºÍcmm£¬´ËÆÚ¼äÎÞ·¨±£Ö¤ÔÀ´µÄÈÎÎñ»òÐéÄâ´æ´¢ÇøÈÔȻʹÓÃÕâЩcmsºÍcmm£»
¡¡¡¡
¡¡¡¡3. µ÷ÓÃcmsRelease()Êͷžä±ú¡£
¡¡¡¡
¡¡¡¡¹Ò½Ó¡¢·ÅÆú¾ä±úµÄ²Ù×÷²½Ö裺
¡¡¡¡
¡¡¡¡1. µ÷ÓúÏÊʵÄcmsGetHandle*()»òcmsNewHandle*()°²È«µÄ»ñµÃcmsºÍcmmµÄ¾ä±ú£»
¡¡¡¡
¡¡¡¡2. µ÷ÓúÏÊʵÄcmsAttachNew*()»òcmsDiscard()¡£
¡¡¡¡
¡¡¡¡3.1.3 »ù±¾ÉèÖÃ
¡¡¡¡
¡¡¡¡ÄÚºËÓµÓÐ×Ô¼ºµÄkernel_cms¡£ÄÚºËÔÚstart_kernel()µÄ¿ªÍ·£¨build_all_ zonelists()Ö®ºó£¬trap_init()֮ǰ£©Ê×Ïȵ÷ÓÃcms_cmm_static_init()Ϊkernel_cms¹¹Ô쾲̬µÄ³õʼcmm&cms£¬ÆäÖÐÖ»°üº¬Ö´Ðб¾Äں˵Ĵ¦ÀíÆ÷ºÍËùÔÚ½ÚµãµÄÄÚ´æ¿é£¬²¢ÇÒ½«kernel_cms -> mems_allowed¸³Öµ-1UL£¬ÔÊÐíÄÚºËÔÚcpu_init()¹ý³ÌÖÐʹÓÃËùÓÐÄÚ´æ¿é¡£È»ºó£¬ÄÚºËÔÚstart_kernel()µÄ½áβִÐÐcms_cmm_init()£¬´´½¨cmmºÍcms¸ßËÙ»º´æ£¬Îªkernel_cms¹¹Ôì°üº¬ËùÓд¦ÀíÆ÷ºÍÄÚ´æ¿éµÄcmm&cms£¬²¢´«µÝ¸øinit_task¡£Èç¹ûϵͳÆô¶¯Ê±ÉèÖÃÁËcpumemset_minimal²ÎÊý£¬ÔòʹÓõÄÊÇcms_cmm_static_init()¹¹ÔìµÄ×îС¼¯¡£
¡¡¡¡
¡¡¡¡Ã¿¸ö½ø³Ì¶¼ÓµÓÐÁ½¸öcms£ºcurrent_cmsÓ°Ïì×Ô¼ºµÄ´¦ÀíÆ÷·ÖÅäºÍÐéÄâ´æ´¢Çø´´½¨£¬ child_cms¼Ì³Ð¸øÓÉ×Ô¼ºforkµÄ×Ó½ø³Ì¡£Ã¿¸öн¨½ø³ÌµÄcurrent_cmsºÍchild_cms¶¼¼Ì³Ð×Ô¸¸½ø³ÌµÄchild_cms¡£
¡¡¡¡
¡¡¡¡¡¾include/linux/sched.h¡¿
¡¡¡¡296 struct task_struct {
¡¡¡¡:
¡¡¡¡325¡¡¡¡¡¡¡¡ cpumask_t cpus_allowed;
¡¡¡¡:
¡¡¡¡429¡¡¡¡¡¡¡¡ cpumemset_t * current_cms;
¡¡¡¡430¡¡¡¡¡¡¡¡ cpumemset_t * child_cms;
¡¡¡¡431¡¡¡¡¡¡¡¡ /* stash mems_allowed of most recent vma to page fault here */
¡¡¡¡432¡¡¡¡¡¡¡¡ unsigned long mems_allowed;
¡¡¡¡:
¡¡¡¡462 };
¡¡¡¡
¡¡¡¡¡¾kernel/fork.c¡¿
¡¡¡¡620 int do_fork(unsigned long clone_flags, unsigned long stack_start,
¡¡¡¡621¡¡¡¡¡¡¡¡¡¡¡¡ struct pt_regs *regs, unsigned long stack_size)
¡¡¡¡622 {
¡¡¡¡:
¡¡¡¡751¡¡¡¡¡¡¡¡ SET_CHILD_CMS(p, current);
¡¡¡¡£º
¡¡¡¡871 }
¡¡¡¡
¡¡¡¡¡¾include/linux/cpumemset.h¡¿
¡¡¡¡173 /*
¡¡¡¡174¡¡* Set child's current, child and alloc cpumemset
¡¡¡¡175¡¡* from parent's child_cms (used in fork).
¡¡¡¡176¡¡*/
¡¡¡¡177
¡¡¡¡178 #define SET_CHILD_CMS(child, parent) do {¡¡¡¡¡¡ 179¡¡¡¡¡¡¡¡ cpumemset_t *cms = (parent)->child_cms; 180¡¡¡¡¡¡¡¡ CMS_TRACE_HOOK("fork task", cms);¡¡¡¡¡¡ 181¡¡¡¡¡¡¡¡ atomic_inc(&cms->counter);¡¡¡¡¡¡¡¡¡¡¡¡¡¡182¡¡¡¡¡¡¡¡ (child)->current_cms = cms;¡¡¡¡¡¡¡¡¡¡¡¡ 183¡¡¡¡¡¡¡¡ update_cpus_allowed(child);¡¡¡¡¡¡¡¡¡¡¡¡ 184¡¡¡¡¡¡¡¡ atomic_inc(&cms->counter);¡¡¡¡¡¡¡¡¡¡¡¡¡¡185¡¡¡¡¡¡¡¡ (child)->child_cms = cms;¡¡¡¡¡¡¡¡¡¡¡¡¡¡ 186¡¡¡¡ } while (0)
¡¡¡¡
¡¡¡¡Ã¿¸öÐéÄâ´æ´¢Çø¶¼ÓµÓи÷×ÔµÄvm_mems_allowedλÏòÁ¿¡£Ð½¨ÐéÄâ´æ´¢ÇøµÄvm_mems_ allowedͨ¹ýcms_current_mems_allowed()¼Ì³Ð×Ô´´½¨ÕßÈÎÎñcurrent_cmsµÄmems_allowed¡£¶ÔÓÚ±»¹Ò½ÓµÄÒÑ´æÔÚµÄÐéÄâ´æ´¢Çø£¬ÈçmmapµÄÄÚ´æ¶ÔÏóºÍ¹²ÏíÄÚ´æÇø£¬Ôò¼Ì³Ð×Ô¹Ò½Ó½ø³Ìcurrent_cmsµÄmems_allowed¡£cmsµÄmems_allowedλÏòÁ¿ÓÉmems_allowed_build(cms)¸ù¾ÝcmsÖеÄËùÓÐÄÚ´æ¿éÁбíÀ´¹¹Ôì¡£
¡¡¡¡
¡¡¡¡¡¾include/linux/mm.h¡¿
¡¡¡¡45 struct vm_area_struct {
¡¡¡¡£º
¡¡¡¡77¡¡unsigned long vm_mems_allowed;¡¡/* cpumemset managed memory placement */
¡¡¡¡£º
¡¡¡¡81 };
¡¡¡¡
¡¡¡¡¡¾kernel/cpumemset.c¡¿
¡¡¡¡1538 static unsigned long
¡¡¡¡1539 mems_allowed_build(cpumemset_t *cms)
¡¡¡¡1540 {
¡¡¡¡1541¡¡¡¡¡¡¡¡ int i;
¡¡¡¡1542¡¡¡¡¡¡¡¡ unsigned long mems_allowed = 0;
¡¡¡¡1543
¡¡¡¡1544¡¡¡¡¡¡¡¡ for (i = 0; i < cms->nr_mems; i++)
¡¡¡¡1545¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ mems_allowed |= mems_allowed_value(cms, cms->mems + i);
¡¡¡¡1546¡¡¡¡¡¡¡¡ return mems_allowed;
¡¡¡¡1547 }
¡¡¡¡
¡¡¡¡3.2 ½ø³Ìµ÷¶È¼°ÄÚ´æ·ÖÅä
¡¡¡¡Äں˵÷ÓÃupdate_cpus_allowed(struct task_struct *p)¸ù¾ÝÈÎÎñµÄcurrent_cmsµÄ´¦ÀíÆ÷Áбí¸ü¸ÄËüµÄcpus_allowedλÏòÁ¿£¬´Ó¶øÓ°Ïì¸ÃÈÎÎñµÄ´¦ÀíÆ÷µ÷¶È¡£
¡¡¡¡
¡¡¡¡¡¾kernel/cpumemset.c¡¿
¡¡¡¡585 void
¡¡¡¡586 update_cpus_allowed(struct task_struct *p)
¡¡¡¡587 {
¡¡¡¡588 #ifdef CONFIG_SMP
¡¡¡¡589¡¡¡¡¡¡¡¡ int i;
¡¡¡¡590¡¡¡¡¡¡¡¡ cpumemset_t *cms = p->current_cms;
¡¡¡¡591¡¡¡¡¡¡¡¡ cpumask_t cpus_allowed = CPU_MASK_NONE;
¡¡¡¡592
¡¡¡¡593¡¡¡¡¡¡¡¡ for (i = 0; i < cms->nr_cpus; i++)
¡¡¡¡594¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ __set_bit(cms->cmm->cpus[cms->cpus[i]], &cpus_allowed);
¡¡¡¡595¡¡¡¡¡¡¡¡ if (any_online_cpu((cpumask_t*)&cpu_online_map) < NR_CPUS) {
¡¡¡¡£º
¡¡¡¡609¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ set_cpus_allowed(p, &cpus_allowed);
¡¡¡¡610¡¡¡¡¡¡¡¡ }
¡¡¡¡611 #endif
¡¡¡¡612 }
¡¡¡¡
¡¡¡¡Äں˸ù¾ÝÐéÄâ´æ´¢ÇøµÄvm_mems_allowedλÏòÁ¿ÎªÈÎÎñ·ÖÅäÄڴ棬Èç¹ûÊÇÔÚÖжÏÉÏÏÂÎÄÖУ¬ÐéÄâ´æ´¢ÇøµÄÄÚ´æ·ÖÅäÔòÒÀÀµÓÚkernel_cmsµÄmems_allowed¡£ºêCHECK_MEMS_ALLOWED(mems_allowed, zone)¸ºÔð¼ì²ézoneËùÔڵĽڵãÊÇ·ñÂäÔÚmems_allowedÉ趨µÄÄÚ´æ¿é¼¯ºÏÄÚ¡£
¡¡¡¡
¡¡¡¡¡¾mm/memory.c¡¿
¡¡¡¡1383 int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma,
¡¡¡¡1384¡¡¡¡¡¡¡¡ unsigned long address, int write_access)
¡¡¡¡1385 {
¡¡¡¡£º
¡¡¡¡1390¡¡¡¡¡¡¡¡ /*
¡¡¡¡1391¡¡¡¡¡¡¡¡¡¡* We set the mems_allowed field of the current task as
¡¡¡¡1392¡¡¡¡¡¡¡¡¡¡* the one pointed by the faulting vma.¡¡The current
¡¡¡¡1393¡¡¡¡¡¡¡¡¡¡* process will then use the correct mems_allowed mask
¡¡¡¡1394¡¡¡¡¡¡¡¡¡¡* if a new page has to be allocated.
¡¡¡¡1395¡¡¡¡¡¡¡¡¡¡*/
¡¡¡¡1396¡¡¡¡¡¡¡¡ if(!in_interrupt())
¡¡¡¡1397¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ current->mems_allowed = vma->vm_mems_allowed;
¡¡¡¡£º
¡¡¡¡1417 }
¡¡¡¡
¡¡¡¡¡¾mm/page_alloc.c¡¿
¡¡¡¡334 struct page * __alloc_pages(..)
¡¡¡¡£º
¡¡¡¡343¡¡¡¡¡¡¡¡ if (in_interrupt())
¡¡¡¡344¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ mems_allowed = kernel_cms->mems_allowed;
¡¡¡¡345¡¡¡¡¡¡¡¡ else
¡¡¡¡346¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ mems_allowed = current->mems_allowed;
¡¡¡¡347¡¡¡¡¡¡¡¡ if (mems_allowed == 0) {
¡¡¡¡348¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ printk(KERN_DEBUG "workaround zero mems_allowed in alloc_pages\n");
¡¡¡¡349¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ mems_allowed = -1UL;
¡¡¡¡350¡¡¡¡¡¡¡¡ }
¡¡¡¡£º
¡¡¡¡if(!CHECK_MEMS_ALLOWED(mems_allowed, z))
¡¡¡¡continue;
¡¡¡¡£º
¡¡¡¡450 }
¡¡¡¡
¡¡¡¡¡¾include/linux/cpumemset.h¡¿
¡¡¡¡194 /* Used in __alloc_pages() to see if we can allocate from a node */
¡¡¡¡195 #define CHECK_MEMS_ALLOWED(mems_allowed, zone) 196¡¡¡¡¡¡¡¡ ((1UL << (zone)->zone_pgdat->node_id) & (mems_allowed))
¡¡¡¡
¡¡¡¡ÎªÐéÄâ´æ´¢Çø·ÖÅäҳʱ£¬Èç¹ûµ±Ç°Ö´ÐиÃÈÎÎñµÄ´¦ÀíÆ÷°üº¬ÔÚ¸ÃÐéÄâ´æ´¢ÇøµÄcmsÖУ¬Ôò´Ó¸Ã´¦ÀíÆ÷µÄÄÚ´æ¿éÁбíÖзÖÅ䣬·ñÔò´Ó¸ÃÐéÄâ´æ´¢ÇøµÄcms¶¨ÒåµÄCMS_DEFAULT_CPUµÄÄÚ´æ¿éÁбíÖзÖÅä¡£
¡¡¡¡
¡¡¡¡3.3 APIÉè¼Æ
¡¡¡¡CpuMemSetsÌṩÁËһϵÁеÄÄں˼¶ºÍÓ¦Óü¶µÄ±à³Ì½Ó¿Ú£¬·Ö±ð¶¨ÒåÔÚÄں˵Äinclude/linux/cpumemset.hÎļþºÍ¿â´úÂëCpuMemSets/cpumemsets.hÎļþÖУ¨Èç±í2Ëùʾ£©¡£
¡¡¡¡
¡¡¡¡Í¨¹ýµ÷ÓÃÓû§¼¶½Ó¿Ú¶Ôcmm&cms½øÐÐÉèÖý«µ¼ÖÂÄں˵ĵ÷¶ÈÆ÷ºÍÄÚ´æ·ÖÅäÆ÷ËùʹÓõÄϵͳλÏòÁ¿Èçcpus_allowedºÍmems_allowedµÄ±ä»¯£¬´Ó¶øʹÄں˵÷¶È´úÂëʹÓÃеÄϵͳ´¦ÀíÆ÷ºÅ¡¢ÄÚ´æ·ÖÅä´úÂë´ÓÐÂÄÚ´æ¿éÖзÖÅäÄÚ´æÒ³£»µ«ÊÇ£¬ÔÏÈ´Ó¾ÉÄÚ´æ¿éÖзÖÅäµÄÄÚ´æÒ³½«²»»á·¢ÉúǨÒÆ£¬³ý·ÇÇ¿ÖƲÉÓÃÆäËûÊֶΡ£¾ßÌåÀ´Ëµ£¬ÏµÍ³ÔÚcmsAttachNewTask()¡¢cmsExchangeTask()ºÍcmsExchangePid()¹ý³ÌÖУ¬Ö´ÐÐupdate_cpus_allowed()¸ù¾ÝÈÎÎñµÄcurrent_cmsµÄµ±Ç°´¦ÀíÆ÷Áбí¸ü¸ÄËüµÄcpus_allowedλÏòÁ¿£»ÔÚcms_set()¹ý³ÌÖУ¬Ö´ÐÐmems_allowed_build()¸ù¾ÝÈÎÎñµÄcurrent_cmsµÄµ±Ç°ÄÚ´æ¿éÁбí¸ü¸Äµ±Ç°ÐéÄâ´æ´¢Çø»òÈÎÎñ¡¢Äں˵Ämems_allowedλÏòÁ¿¡£
¡¡¡¡
¡¡¡¡¡¾kernel/cpumemset.c¡¿
¡¡¡¡1661 static int
¡¡¡¡1662 cms_set(unsigned long *preq, char *rec, int size, target_option cmm_or_cms)
¡¡¡¡£º
¡¡¡¡1713¡¡¡¡¡¡¡¡ if (choice == CMS_VMAREA) {
¡¡¡¡£º
¡¡¡¡
¡¡¡¡1772¡¡¡¡¡¡¡¡vma->vm_mems_allowed = mems_allowed_build(newhan.set);
¡¡¡¡£º
¡¡¡¡1792¡¡¡¡¡¡¡¡ } else {
¡¡¡¡£º
¡¡¡¡1822¡¡¡¡¡¡¡¡¡¡ newhan.set->mems_allowed = mems_allowed_build(newhan.set);
¡¡¡¡£º
¡¡¡¡1840¡¡¡¡¡¡¡¡ }
¡¡¡¡:
¡¡¡¡1842 }
¡¡¡¡
¡¡¡¡ÔÚȨÏÞ±£»¤·½Ã棬ֻÓиùȨÓû§²Å¿ÉÒÔÐÞ¸ÄÄÚºËËùʹÓõÄcms&cmmºÍÈκÎÈÎÎñµÄcms&cmm£»¶øÒ»°ãÓû§Ö»ÄÜÐÞ¸Ä×ÔÉíµÄÈÎÎñºÍÐéÄâ´æ´¢ÇøËùÓµÓеÄcms&cmm£»¾ßÓÐÏàͬuidµÄÈÎÎñÖ®¼ä¿ÉÒÔ»¥ÏàÐ޸ĶԷ½µÄcms&cmm¡£Ö»ÓиùȨÓû§²Å¿ÉÒÔÀ©Õ¹×ÔÉíµÄcmm£¬Ò»°ãÓû§Ö»¿ÉÒÔËõС×Ô¼ºµÄcmm¡£
¡¡¡¡
¡¡¡¡¡¾kernel/cpumemset.c¡¿
¡¡¡¡409 cmshandle_t
¡¡¡¡410 cmsGetHandlePid(int choice, pid_t pid, int do_check_perm)
¡¡¡¡411 {
¡¡¡¡£º
¡¡¡¡425¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ if (pid &&
¡¡¡¡426¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ do_check_perm &&
¡¡¡¡427¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ (current->euid ^ p->suid) &&
¡¡¡¡428¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ (current->euid ^ p->uid) &&
¡¡¡¡429¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ (current->uid ^ p->suid) &&
¡¡¡¡430¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ (current->uid ^ p->uid) &&
¡¡¡¡431¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ !capable(CAP_SYS_ADMIN))
¡¡¡¡432¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ han.error = -EPERM;
¡¡¡¡£º
¡¡¡¡442 }
¡¡¡¡
¡¡¡¡¡¾kernel/cpumemset.c¡¿
¡¡¡¡1478 /*
¡¡¡¡1479¡¡* Unless you have CAP_SYS_ADMIN capability, you can only shrink cmm.
¡¡¡¡1480¡¡*/
¡¡¡¡1481
¡¡¡¡1482 static int
¡¡¡¡1483 cmm_restrict_checking(cpumemmap_t *oldmap, cpumemmap_t *newmap)
¡¡¡¡1484 {
¡¡¡¡1485¡¡¡¡¡¡¡¡ int i;
¡¡¡¡1486
¡¡¡¡1487¡¡¡¡¡¡¡¡ if (capable(CAP_SYS_ADMIN))
¡¡¡¡1488¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ return 0;
¡¡¡¡1489
¡¡¡¡1490¡¡¡¡¡¡¡¡ /* newmap must be a subset of oldmap */
¡¡¡¡1491¡¡¡¡¡¡¡¡ for (i = 0; i < newmap->nr_cpus; i++)
¡¡¡¡1492¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ if (!foundin (newmap->cpus[i], oldmap->cpus, oldmap->nr_cpus))
¡¡¡¡1493¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ return -EINVAL;
¡¡¡¡1494¡¡¡¡¡¡¡¡ for (i = 0; i < newmap->nr_mems; i++)
¡¡¡¡1495¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ if (!foundin (newmap->mems[i], oldmap->mems, oldmap->nr_mems))
¡¡¡¡1496¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ return -EINVAL;
¡¡¡¡1497¡¡¡¡¡¡¡¡ return 0;
¡¡¡¡1498 }
¡¡¡¡
¡¡¡¡ËÄ¡¢ ʹÓþÙÀý
¡¡¡¡Ê¾Àý1£ºÏÔʾµ±Ç°ÈÎÎñcurrent_cmsÖеĴ¦ÀíÆ÷
¡¡¡¡
¡¡¡¡/*
¡¡¡¡* sample1 - display current cpumemset cpus
¡¡¡¡*
¡¡¡¡* Compile with:
¡¡¡¡*¡¡cc sample1.c -o sample1 -lcpumemsets
¡¡¡¡* Displays on stdout the number and a list of the cpus
¡¡¡¡* on which the current process is allowed to execute.
¡¡¡¡*/
¡¡¡¡
¡¡¡¡#include "cpumemsets.h"
¡¡¡¡
¡¡¡¡main()
¡¡¡¡{
¡¡¡¡int i;
¡¡¡¡cpumemset_t *pset;
¡¡¡¡
¡¡¡¡pset = cmsQueryCMS(CMS_CURRENT, (pid_t)0, (void *)0);
¡¡¡¡if (pset == (cpumemset_t *)0) {
¡¡¡¡perror("cmsQueryCMS");
¡¡¡¡exit (1);
¡¡¡¡}
¡¡¡¡printf("Current CpuMemSet has %d cpu(s):\n\t", pset->nr_cpus);
¡¡¡¡for (i = 0; i < pset->nr_cpus; i++)
¡¡¡¡printf("%s%d", (i > 0 ? ", " : ""), pset->cpus[i]);
¡¡¡¡printf("0);
¡¡¡¡exit(0);
¡¡¡¡}
¡¡¡¡
¡¡¡¡Ê¾Àý2£ºÉèÖõ±Ç°ÈÎÎñµÄ×ÓÈÎÎñ½öÔËÐÐÔÚ0ºÅ´¦ÀíÆ÷ÉÏ£¬²¢Æô¶¯shÔËÐÐ
¡¡¡¡
¡¡¡¡/*
¡¡¡¡*¡¡sample2 - change child cpumemset cpus to just cpu 0
¡¡¡¡*
¡¡¡¡*¡¡Compile with:
¡¡¡¡*¡¡cc sample2.c -o sample2 -lcpumemsets
¡¡¡¡*¡¡Change the cpus which the child task is allowed
¡¡¡¡*¡¡execute on to just cpu 0.¡¡Start a subshell,
¡¡¡¡*¡¡instead of just exiting, so that the user has
¡¡¡¡*¡¡the opportunity to verify that the change occurred.
¡¡¡¡*/
¡¡¡¡
¡¡¡¡#include
¡¡¡¡
¡¡¡¡main()
¡¡¡¡{
¡¡¡¡int i;
¡¡¡¡cpumemset_t *pset;
¡¡¡¡
¡¡¡¡pset = cmsQueryCMS(CMS_CHILD, (pid_t)0, (void *)0);
¡¡¡¡if (pset == (cpumemset_t *)0) {
¡¡¡¡perror("cmsQueryCMS");
¡¡¡¡exit (1);
¡¡¡¡}
¡¡¡¡pset->nr_cpus = 1;
¡¡¡¡free(pset->cpus);
¡¡¡¡pset->cpus = (cms_acpu_t *) malloc(sizeof(cms_acpu_t));
¡¡¡¡pset->cpus[0] = (cms_acpu_t)0;
¡¡¡¡if (cmsSetCMS(
¡¡¡¡CMS_CHILD, (pid_t)0, (void *)0, (size_t)0, pset) < 0) {
¡¡¡¡perror ("cmsSetCMS");
¡¡¡¡exit(1);
¡¡¡¡}
¡¡¡¡cmsFreeCMS (pset);
¡¡¡¡printf ("Invoking subshell running on cpu 0.0);
¡¡¡¡execl("/bin/sh", "sh", 0);
¡¡¡¡exit (2);
¡¡¡¡}
¡¡¡¡
¡¡¡¡ÏÈÔËÐÐʾÀý2£¬ÔÙÔËÐÐʾÀý1£º
¡¡¡¡
¡¡¡¡# PS1='Sub> ' ./sample2
¡¡¡¡Invoking subshell running on cpu 0.
¡¡¡¡Sub> ./sample1
¡¡¡¡Current CpuMemSet has 1 cpu(s):
¡¡¡¡0
¡¡¡¡Sub> exit
¡¡¡¡
¡¡¡¡Îå¡¢ С½á
¡¡¡¡CpuMemSetsͨ¹ýÔÚÒÑÓеÄLinuxµ÷¶ÈºÍÄÚ´æ·ÖÅä´úÂë»ù´¡ÉÏÔö¼Ócpumemmap£¨cmm£©ºÍcpumemset£¨cms£©Á½²ã½á¹¹£¬ÎªLinuxÌṩÁ˽«ÏµÍ³·þÎñºÍÓ¦Óðó¶¨ÔÚÖ¸¶¨µÄ´¦ÀíÆ÷ÉϽøÐе÷¶È¡¢ÔÚÖ¸¶¨µÄ½áµãÉÏ·ÖÅäÄÚ´æµÄ»úÖÆ¡£´ÓÊý¾Ý½á¹¹ºÍ¿ØÖÆ»úÖÆÉÏ¿´£¬Ä¿Ç°µÄʵÏֱȽϼòµ¥ÊµÓ㬵«ÊÇÈÔÈ»ÓнøÒ»²½ÓÅ»¯µÄ¿Õ¼ä¡£µ«ÊÇ£¬CpuMemSets½ö½öÊÇÌṩÁËÒ»Ì×ÍÚ¾ò±¾µØ·Ã´æÓÅÊÆ¡¢ÓÅ»¯LinuxϵͳµÄNUMAÐÔÄܵĻúÖÆ£¬ÈçºÎ»ùÓÚÕâÖÖÖ§³ÖÊÖ¶ÎÖƶ¨ºÏÊʵÄNUMAϵͳÓÅ»¯²ßÂÔÐèÒª½øÐиü¶à¸üÉîÈëµÄÑо¿¡£