mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-06-25 02:27:10 +08:00
[docs update]完善操作系统常见面试题总结(上)篇
This commit is contained in:
parent
51e4380716
commit
148ef34874
@ -1 +1 @@
|
||||
<mxfile host="Electron" modified="2022-08-21T07:59:47.276Z" agent="5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.4.5 Chrome/83.0.4103.122 Electron/9.1.0 Safari/537.36" etag="QasVtwjBaJyNZ0lqSJkR" version="13.4.5" type="device"><diagram id="tmrIvn8UqugqhCCRZjQR" name="Page-1">7Vzbkps4EP0aVe0+eIs74hFf5lK1k8zGs5XsvslGttlg5MVybOfrIxlhbmLGyWAYe5hUxdCNBPQ53Wo1AqAPlrvbCK0WD8TDAdAUbwf0IdA01dF19sMl+1jiOHYsmEe+Jw5KBWP/OxZCRUg3vofXuQMpIQH1V3nhlIQhntKcDEUR2eYPm5Egf9YVmuOSYDxFQVn62ffoIpZCzU7ld9ifL5Izq5YTa5YoOVjcyXqBPLLNiPQR0AcRITTeWu4GOODGS+wSt7up0B4vLMIhPaWBNXC/DzX3+2dt+2/vY//2rx7c90Qv31CwETcMRhC4KnAhGNnANUDfBSMT9FUANXEfdJ8YJyKb0MO8fxXo/e3Cp3i8QlOu3TI6MNmCLgOhnpGQCnzZlbJ9PwgGJCDRoS/dMzH0DCZf04h8xRkN1Ca6ZTHNPEBrDidvfbQm73pKlv5UbJfNktwjjijeZUTCTLeYLDGN9uyQRGuYcRPBWUsXEG5TBqgJrIsM+paQIUG6+bHrFBe2IaD5CZg0CUwmh8YxOEzsf45XIzAhDGdTGUzWFOLJrEWYTLttmHQJTMyDBsBxD251A5xhMzDNZtiaSmHybGeiKG16k9M2TEnwztgeeyzqi10S0QWZkxAFo1TaT9HhBkuP+ZOQlTDWf5jSvQAFbSjJI1ZpyjXZRFP8zPUa8XH8Gp81eIQDRP1v+ZFLZj3R9JH47FKOQBmGkgPKhgUAKIrmmIpWBQyOl/HrsBhV3uMq3Hv6I+DoDXkPnGK590ygaZhteo9ttu498LK8x2zHe6DRrPeYEu+xQX8IHPWw0QfOoBnvwSrL5WyZ9ziWraM2Mzmotu09lgQmCzgMF4VvwCFwR2Dk8FDHAh4PezbPGxoBTp0gFWsy4BTFGrGriHvIpRn8r01AW8/5bKnfQQe4ziE1VwC0moFPUUwFz+TwqUM2jr49+Jz2Z1bmZY1mmtbOcGYVETj3cNZKloF3Pv0imvPtf/j2H6bYG+4yquFe7FwAlu1CmdxmNkRWx0Hl5ThImMan+yQMziPk+TgNbCEJORk8tF4cI2scEpMKnl5TNNPyhpUWIGxJNFOLM6v6wplzYeFMbyecHQeehnzAUtvAhcER7b9kdzIBje+mEe2wV0NIE3jG5nzOIErdwL/ObySluyuJUSckzNIYpZ0rRiWud5qtT8iLcxlrMUnOprbZbLZY8jH5P2ld+/BXTp7jv3pQMsxC6U1S5dHMJvNi/acG7XcJEtRaB+mnota7BMlRJCApjYIkqWt3IOVAkj1g1fVGQZKUTzUroNxCKxTm0LL+3/Bn9sy8B+O4PEmZT37TLaCxkyuGKn6t3w/WUrghe+sDRvxY1VrtYgWzFu2hwJ+HsSbAM3rQJGdgW3P+e/f09JhcDru9+IpiVYlKvNMCX3IQi8xDnHY4ZShiJu9z9PwpClyhWPqed8hCZWzMp0LF5CZbWQrQBAd9NP06P7QpXEUdXLILXDLKXDIkVDpfeiOpCP4ClZSUTUpKKE2p5lSik9KqxKnhh3FHKTmlTP2tUQpWUsrzv0kZdRoJXiSmlGdVvfCDAV+KlWCWHqhrhuZouNx2/MBC20gHUAFQffz4qB937h/cbNCLO8+fsETco/hglrz00i2VtJ1Ekvt9hXXeubOXchHJBFmaMJ7N2w3JorxaOfwa9r2O/zfP5DEvcbkjbWaEgm9shDJkM9Hr4OwTDkJMO9rWQFurGGtbp61sbn4dtB2P7zrOnoOzVtucrS5VXHqK+zSoKeN/55w11TxnbUlO2yxnJcveroSzfw87ztYSZ5W3xtnqOt6lc/a+o+w5Ss9Q8hijWcpeb53Q/dRxtpbUQHtrnHWudgp2P3joyl3nKHe1TtpkTniFpP3gPnWcrSOfLTxEhJIlXc1y9nofK3y6T58hfhw/3hx3+rddAK4l0y2+diVbn6g2ymbtatk8HNx1rK2DtXYh1239cYN57tJte6TNz886ztaWNrSe6l5v6fbBHXQ1hTqyg8L0zJEsjG+Ws9WlW3YCxHmyQNFavKCU0GJDZz34Czx99TrgWBH3yzUhiZYoyOi2wmhcaShimWeAKaNNb81fNArn5ZaVq4tjjc/YE4o+ldyKZBqhcD1jPSV9Cp4oWxJ5+fMdG3r+ehWgfSz1w8BP2swCgmiho6KFB+MHpr8ZDCvdTu5gL6yTz3vI6d72pupzjmqWfEmVLUcrvtBYnzNJCnTdx8d6xRVYrX/JwJLUpCRfgLEAHAHX5IDBG+A29EWlE75NcRJyVR+wOAOisjeHGka0PF0ov0Z8YrKRxeMM+cfzcTFDDhXWhJZa/KpB2/U1q/zwrexTHVqxoPWn+1Z5VNM7tCrQan0SapfHNqNDqwKtM06/2G76weL42xjpZ5/10Q8=</diagram></mxfile>
|
||||
<mxfile host="Electron" modified="2023-04-01T13:53:49.741Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="tIdtzWxSp10nsOGoVtAv" version="20.3.0" type="device"><diagram id="tmrIvn8UqugqhCCRZjQR" name="Page-1">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</diagram></mxfile>
|
@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2023-03-31T09:15:45.427Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="Hv_zxBbvRWb4T7KhPdXo" version="20.3.0" type="device"><diagram id="21OmZePq3j6wwnkUTsuK" name="Page-1">7Vptc9soEP41fLQHvVr6KNlye512rnOZaS8fiY1lNbLwSTi28+sPJJCFkFPn/Do5TzIJLLBI7MOzuwhgDRebTzlazr+RKU6BCacbYI2AaRoGdNk/LtlWkoHnV4I4T6ai007wkLxiIYRCukqmuFA6UkJSmixV4YRkGZ5QRYbynKzVbjOSqrMuUYw1wcMEpbr0ZzKl80rqmYOd/DNO4rmc2XDF+z2hyXOck1Um5gOmNXbH47FXNS+Q1CVetJijKVk3RFYErGFOCK1Ki80Qp3xt5bJV48Z7WuvnznFGDxlgj//Cz1Zvu52Z0eL1x0/38w/UE8Yr6FauR/lGmI+BwApJTuckJhlKvxKyZEKDCX9hSrfCkmhFCRPN6SIVrexx8u3fYnxZeWxWRhulthW1GcmoUGm4oj5GiyTlHb5gGuYoyQr2qN9IRmR/ssonfMScUoYW07EC9octAP/DOxT9mJA4xWiZFP0JWZQNk6LsOp5V2lmxqd8xQzFDtTJ4qsFnt+BCVMjn2LfKEtcojzF9o59Zw4JtN0wWmK0QG5fjFNHkRX0OJHAf1/12tmcFYf53QEEA/gWlKzETiBzgsV8DRB4IIhB6Glr48nxFT4wTFAygNIkzVp6wpcI5E7zgnCZs0wWiYZFMp1xHmOMieUVPpT6OgyVJmN24cicEzqgDGSmfLqw335CkJC8fRm6/2wEPf2u8AR00Jt54xw5NWO3fqTo2hPYe7FuVIkHDFZbegR2h+jtf/51ew1S0StKWCshsVjBEt6FXP99/R6OhoTHDax1+acr8BMfRep5Q/LBEpUnXzFWpgNToJUnTBnLsYWD7AyYvaE6esWzJSIZvG04aG+1FiA9VS9qivt45PQMK2bzh8Fy4HzNH8Y2pWTjHaLo9m40h9Cxv/KFtbNqqkc3BtY1saUameJFkiLII41yGHtq2Yzsf2tBOezdb1za0YXfGBg+iKhb/dMFlXXlsVv6PwaV9YHDpXDO4NByNCP74k6uMBiAYAZYzslgzjHi4GbnAHwMG8MgGYQC8sCyEINRzlXv0eanos9ree/mIRZ/QagWg9kkC0IHKc+6l4k/TvCyfwb5zZ7R3Mpp1TUYz9dAGRD7wIP/lifOAs9edsa7FWOaew5SasaBpq4xlHEdY5+ckW8+YVlmWZPHZQunI9w3H+NChtO3fWs5kGJo9T+lnBrZyLtuHxuCdzqZs/Y7zhL0vZ6u60y2A4SQeyDnQA131wFYGQ2pMzVxPwOLoIY+jPY/H0TzK1kJp7qFYlG3wANy3ecR9d1VXC67fZqge7Ndf2U4bXPc8Rat3qeBaTwbXKKFndWT20GBJ5kd2ZJZzc2dCnh4iawbOpgH/issZJUVFkUxUu6qeT/NEm4TWp0Gs/Ngo75wZr0hf1v118pB06xYAchLnZh7o3Pak/A04OR1okrIjqcmGKpprdEsV1WuKUTug6opa28KCLUXVOmiKTvYhy9c3QeSBkOWJVnnoFYCgdMe+DwKvo+nul6/ml73f+mXHNY+D+wVOsuDZWbjzUP53Nz4kd8MGd8M3uftWMHbRQ649KcaFWNhqkWf7AsDBLOy1sux20HFmFpavrrCwC/xBmQv5ZcHmuRALEr2BSIo4HctsSiRRHv9awQe6vHCn5qud7sHubVGf7jnQVAB3ooypFUw46vgzkrh+9gdMN6XCfAoM3X9WRDb0ihIrzJjQcJeb0haynZXi8n91zSsYlggf8r1QnQ6ErDAuJcEX9II+8Zuactan/Mg52YYbifOHIOTBj5zqF5uqvBTan2RyNlCBsB7d3ngMV1Tdc915XiMpFKLD92ZXAqr6xT17sZFktj/ZNLZrWP6UOilDKMmE0uIZ08lcVuQd0ltyh8dlrUbLw3Qdv3odHq7tiQ7IWll1d9222pm7O81W9C8=</diagram></mxfile>
|
@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2023-03-28T10:09:32.332Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="t5AzQ7swnX1_AHZTWmu2" version="20.3.0" type="device"><diagram id="xGMrVERaUssHp3SnbKha" name="Page-1">7Vltc5s4EP41+hgP74aPgE06TXLXufSuyUcFZKDByBWyY/fX3wrEm8GpmzSp22Yy40ir1a7RPrvPyiDdX27PGV4lVzQiGdKUaIv0GdI0VVUs+Ccku0oytZ1KELM0kkqt4Dr9SqRQkdJ1GpGip8gpzXi66gtDmuck5D0ZZow+9NUWNOt7XeGYDATXIc6G0k9pxJNKamvTVv6OpHFSe1Yt+Xx3OLyPGV3n0h/S9MAKgsCulpe4tiUftEhwRB86In2OdJ9RyqvRcuuTTJxtfWzVvuDAavO9Gcn5MRsu/l3ON1jZYH51cbP+75/1p613JoNX8F19HiSC45FTynhCY5rjbN5KvfKZibCqwKzVuaR0BUIVhJ8J5zsZa7zmFEQJX2ZyFb4w293I/eXkVkwmZj2dbbuLs52cLWjOpVFV6Bac0fsmaprUCPAyzcSW94R7DKd5AQ94RXNaW6BrFgobCeeAMc3UXfiAYxMfQqGYxJTGGcGrtJiEdFkuhEWpGiwq6zDs2jc1T3oYRkUGqqjdHgpFDX7MYsIf0dMrPRGnjgMZ83NClwTODBQYyTBPN32YY5ktcaPXIgYGEjTfASBpd4OztfSE5lPkGMi10dxCto28qZDA1PbQ3ESei+xggLoWUwIgD0nKyfUKl+f1AHWnj599HCzSLPNpRllpSzd813CmDT7qlZzm5LQhsiGMk+2jQZWrjqwpsuZqipw/tBVMretO0qlelvJCMJi+1ZFTqSP6kXXE+Fl15N3lzGfGx/tb+++/LjLXu/BvxurIR5H3Y6i6xHfQg/SQgLM0zmEcwmkRSHZPpFIKJO/KhWUaRRXoSJF+xXelPYGFFU0hUsK46SFzNoKOTLjzGrLvFBpJ93WwBunbNC3SX9sLdON6OJ8Opr8y0Uxb7ZWAM62aHh0tafyDeP6OGdXob6GLRQEw2g9v852eXjL0EeYAwnCQC4RhI1dFti+Yw9OR55UDDzmBWPIUZOstzbwKl5xwRTieNjTHODHeGEbvVXmjpYrb7tofyRvGkbxh/mjeKLe6jOFdR0HW5WGhklC2rH4LpJvKHhgri08tWaMkpb2R1CB5HyMpy5r2Scp4Hklt+2YazjJfi7OMX4GzFnZIwvC3vv8Y9l72az+byMwRZByBAyEJxBhuxg7ozN+6maNBYCmndgt2hiAYcEMeueJXyzYhI1wkTXw7sRTyD5gDVeSlRFP00Z6j3w4NEHC6kf5mB9GJozkSxlr2TDZR91Dk7KGjapzkpu7vq3t27G8ZqjqrgaEfxU3qcT/FwQBKkDoAJiQd7wNwnD46FUWKju9rxqrXYfj+NoVqHxgjZGWN4Ft/qTKlDvtYwT82QMMUAHEV5Nm/IlI6VOcbhmmceAF8MoLG2p2XQtDoRWik29GsjMvj7MHF+rKm9cJZUQYMDldRrdW2PJt6HUZx+V8g0UQu9NEG8nwE/YqQBGXxCkqJ+x5v8Ll4b1h7vWPP9Akd2gw5avmmAtowp3H1GVyVrygnYV57QxUomt2nmSAHroSda0CdPtYwfbzyr7TJgVxpLo0W94SHST2p32gqj10vB8A/jPL9O71hDhs6ewTn6vfjHKbtq9eKgtv32/r8fw==</diagram></mxfile>
|
@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2023-03-31T09:06:25.020Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="2QDczarmQEF9iFEacudi" version="20.3.0" type="device"><diagram id="MxLgxCKtOGjb54Z-4qIo" name="Page-1">7VhZb9s4EP41BNoHGzosWX60fDTobrHBBovd7hst0ZISStRSdOz01+/w0mHZSNIDLdAiQMyZIWfI4cznj0b+qjy947jOP7CUUOQ56Qn5a+R5ruuE8CE1T1ozjxZakfEiNZM6xV3xiRilY7SHIiXNYKJgjIqiHioTVlUkEQMd5pwdh9P2jA6j1jgjI8VdgulY+3eRilxrI2/e6W9IkeU2shua8+1w8pBxdqhMPOT523C73UbaXGLryxy0yXHKjj2Vv0H+ijMm9Kg8rQiVubVp0+u2V6ztvjmpxEsWHG8yWh5vbm///NDk93/8mxCcTYyXR0wPxB4jpOAvbgRnVSb3LZ5MrsL/DnKz8Y6dJk3xqQCzv5SZYDwlfAJqMMqrgj2JScIo43oCz3ZvAkjbCsah+ZxHb83sF87bs0rIsETPdee1Ccd4neOq0eqZ1glyEhNMi6zSakr2omeRbiY4vT80QtvxQTBlt2eEUaY+N3O0mKFlhDYhiiIUz9XAQZGLNlsUr6Tyy1P22l3ZiDWuPide589JKG6awdoyndQUF9U47F8N4bBEgoDdAdSb3sRwY1JtsmHzqJO1uD5Dd0l7FE/1FpHV64L5mBeC3NU4kdYjYBHoclFSY5bVYcDFDaRcULrSlQW+/NlqOVvMzR09EGupWEXM4i0uCyox7D0RMYfjN+qkFbPO2YGr2LkQAE1eIPMaQLfJf3JCM80YyyjBddFME1YqQ9Koqdu99g7Dvv/Ai00E04aEQyFc7W+3RQ1AY8JKIji4dOwCxwCTAWI3NMBz7GDNc4wu70Pa3CixgdKs9d3BCQwMorwCXbxf6PIcugQoAjgJJKgsHRRHLbq8+Y3wSn3XynZ7+33aZr8nYZL8VG0z817YNt+sa2YXuubsjkmVLiX3AUnhd6HvCHMxVvduuysNByRIEH/6RwrTwIofzUwlrE/9mesnK50K0VsG0seepVskBbvm+5eKrmBL8aAg4hQ3edsnOsUkHZHFszqCa7DbfAb14DYyIp7jXuO67NVdcKHsrI4TikXxONzupVo0EW5ZAQdpy74taVv2zlk562OaVX1aee4oGDrygzNHOg8jR6o12mN/frcE424Byhb7KFbcDf4vtmgDxA1A1e/Y3Kij4OZ/xzsA3EHHGJBfJ1AFwH38WGJNAa+HpTGURZpKHzEnAPt4p/zJiq/lgVUKghgF6zOsDUGmMlzcviJ6sGveET9C21xFWPMeMyfunjn9jrkOb1fh2JlCSXlDIvNVCt4d+AyGy9l+35BvUp7hVQokr+YiATqnImF9Ttp75CFAyxXazCS3Bn4rNVv1RlFse7F8jx/xO/nCtlF3/AtjQkut0cKVgyX01qINdQ+h1GN+mlQ9tqKPeYWrSLo0bLjLRKPHSozq5Y15iQENvwivNGKP5fTbVsq9Xo3Vn/IpoD5ZZZw2D0QkuRXs2//H+C78CrTJ92ZD2J+PaZMbXXptvJ42gdj9TKIbs/styt/8Dw==</diagram></mxfile>
|
@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2023-03-31T08:50:53.093Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="gw115ZrE0EGb6RdRh1Mx" version="20.3.0" type="device"><diagram id="wgYxP_C74_tortBbW5P-" name="Page-1">7Vhdb5swFP01lraHVGC+zCMkoVul7iWT1lcHHPAKmBnTpP31s7FJIEnVVpvUKqoUhcu519f2vecQHODMq901x01xyzJSAmhlO+AsAIS2bfnyopBHjQQo1EDOaWaCDsCKPhEDWgbtaEbaSaBgrBS0mYIpq2uSigmGOWfbadiGldNZG5yTE2CV4vIU/UUzUWgUweCAfyM0L4aZbd/sb43T+5yzrjbzAegkfpIkSLsrPOQyG20LnLHtCHKWwJlzxoS2qt2clKq2Q9n0uOQZ737dnNTiVQPyHzez+K5deXc3bYjCAre3M9O8B1x2ZNhGv1jxOBSo3yJRSWzgxNuCCrJqcKq8W0kJiRWiKo17Q8tyzkrG5X3NahkUt4Kz+31t5bbjDLfFPuGG1SLBFS0Vf26IiDmmdSuXcMtqZvwr1vF+wkIISQvoOZH8kjtVXyqgvcoZy0uCG9pepazqHWnbhyYbnV2a4/wejM0Mp4U0tX0gXJDdCDKFvSasIoLLlNZeBp4eYkRgO6bp2wOlvAErxnQKzUBsaJzvcx9aKQ3TzTd01j7TWb8UpiF1Pmmy/6dTNIzXbDdr6ROVblVia814RvhMwn2drFQWScxS3WAVwPP1F08KQq7R8s01QF9N9CvjVAfVtETH2kFjpmO8KbBsVg+7GpMdETNc0rzWcEk2YuRRaWY4+921QvtxJ3SThz1KK++vywDEDoi1EYMwAUsEYgsgRyGhCyIElgmI5wChn4rp5iYcCin7MtTSpPw37Sim6+ejpNNUS/Lh4s4jNwz2gjpS2WXIyLcmMoLWqYxseEZGw7j/riL4qaKXVOSCGIFoAZY+CP3eMJr5XgvCedeIdxbOZkP8NL1o4TjwownH+RTOS8LxelHA3kDqMwhnuUtJIyir31s4KCUXLhwXfTThBM8KZ31ougZUAc/q6JjRoWH0uVcg857jS96BOOgN+QpkK1aGEKC5MpAEPeWKrJ6noxg5CulRCxDBPmEEkGt+DeJwoHkyorBe93QvEl4/S2olrSlzzzPy9PBhlLpIifoxkoCiBpWnv8g4KpplapqzUjmIyTo+tpyeasZiQpeiD3j0Rma7p/qAwRl9OG/Xh7w9nIZ73+gvB2f5Fw==</diagram></mxfile>
|
@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2023-03-31T08:50:10.157Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="-jILA7wXZLVi1Mv7-HPo" version="20.3.0" type="device"><diagram id="P8E7oDqwfVw1rBaxzz4C" name="Page-1">7Vhtb5w4EP41ltoPuwK8vH0EsrTqXXWVort+9oIXSL2YM95skl9/Y2Pe9iWXXNu0ylWRNubxMDMe5pkZQDjZ3b0TpCk/8pwy5Fj5HcJXyHFs2/Lgn0LuO8QPwg4oRJUboRG4rh6oAS2D7quctjNByTmTVTMHM17XNJMzjAjBD3OxLWdzqw0p6AlwnRF2in6ucll2aOD4I/6eVkXZW7Y9c74Nyb4Ugu9rYw85OPXSNA267R3pdZmDtiXJ+WEC4TXCieBcdqvdXUKZim0ftu6+9MLu4LegtXzKDVF9SOy//ri/rR38UH6yy/fs82JlfJP3fTxoDuExl1zIkhe8Jmw9orE+M1VaLbgaZX7nvAHQBvCGSnlvnjXZSw5QKXfM7G55Lc2mDWGIWyn4lyH6jpFIya5iKqk+UBkLUtUtOPqR17zXwPciUzpKKSFXHBdH8APHVz9KoF0WnBeMkqZqlxnf6Y2s1aLpttMOy6l+14mNhS4uKhgXw22gtvfjUoyd4WEDiSjfUSnAsCUoI7K6nesnJpuLQW649ROvwLJjGebhPg8N75yVO1chiSioNHeNeQGLiRsjpLPlGZnjdNZuCdvTngAek+Zx1sUsq7y/9yrN4w2/W7TVQwXb6mlZGy5yKhYA65BbGYRXLjLOuOgERLF548JBwUfLM//94K2RfqKcSgZllnaytt8Yc1w0JYHnruFVh0l6JxeEVUXdwYxu5WRHqVmQ/Gbfym7fpPd4RlgV+v/aR+EKRQFaeygIUOzrhYUCG61TFCcK/PqQPder3mJD6v9ib9RnZYy07ezeXb5oGDDp1OyfLRWavjntPYCs65yYO6ZgE40+jl2wwssSxzVsrFCq3BzKStLrhmiSHqCLXa5GrrquGEu6zAJdeJVEq9AfqlS/U/Oa/kSF6pYKSITHS9VpCepvsOalxPZMyzqMDdGxDFZOm6FvXS5bs4Lz3Ori/Yi+9Mr7EH6RPoS9l+1D+Fcf+rc+5KIAGo+r2k9koTgY+tCb36io9TyvCvPbH1Ngt1vqZdn/qsBi/MQC+93qq3vKGkiTOFITyzi3+Oo3iM1WkKI17geYThjr5PJRfKVyKgTQ6pNoI84y75gDXnM8V4zTU4xR3C1iFILxQKkP8HywWqPI1V6kKMITB0F4rZMetiIUhdplvxfW62EKAyQCVY4+hKcOpBYJihJtPVFgpzDURw9Dbd3MJcvl8oQgiqPnmstxdk+oYCBD+asMcgtmJhyrzKvgfTUyG7sqz3W/O0e7eQ+cMs97LWTCwdGLj3NKJuzap2TC34tMwRkyQbakKIwnHIIF5Kqts9dSFXlKJlOgIQ+vUBg8KhyoLUhFJbzSuXoi/K0oOLBhpSgYe4/6patAaPd8Tc75Zf3iystyxQ2W7rz1uGfYEr4kW8KLA5uK2FdmrC7tqmyvdNn2TWcYin0YfSC35J365vgtG1Wf+FGsekNv6gZM6c+by6yezFbdMS9MVj8HGRjZUBYPHzjPzGTHVJkMdLH+0zolvFnw2ihtv1CZlf1F/zXUejVcOxryhoFuwjQ7OPcW/XymweX44bh7kxq/zuP1Pw==</diagram></mxfile>
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 操作系统常见面试题总结
|
||||
title: 操作系统常见面试题总结(上)
|
||||
category: 计算机基础
|
||||
tag:
|
||||
- 操作系统
|
||||
@ -14,8 +14,6 @@ head:
|
||||
|
||||
很多读者抱怨计算操作系统的知识点比较繁杂,自己也没有多少耐心去看,但是面试的时候又经常会遇到。所以,我带着我整理好的操作系统的常见问题来啦!这篇文章总结了一些我觉得比较重要的操作系统相关的问题比如**进程管理**、**内存管理**、**虚拟内存**等等。
|
||||
|
||||
文章形式通过大部分同学比较喜欢的面试官和求职者之间的对话形式展开。另外,我也只是在大学的时候学习过操作系统,不过基本都忘了,为了写这篇文章这段时间看了很多相关的书籍和博客。
|
||||
|
||||
这篇文章只是对一些操作系统比较重要概念的一个概览,深入学习的话,建议大家还是老老实实地去看书。另外, 这篇文章的很多内容参考了《现代操作系统》第三版这本书,非常感谢。
|
||||
|
||||
开始本文的内容之前,我们先聊聊为什么要学习操作系统。
|
||||
@ -25,69 +23,163 @@ head:
|
||||
|
||||
**简单来说,学习操作系统能够提高自己思考的深度以及对技术的理解力,并且,操作系统方面的知识也是面试必备。**
|
||||
|
||||
关于如何学习操作系统,可以看这篇回答:[https://www.zhihu.com/question/270998611/answer/1640198217](https://www.zhihu.com/question/270998611/answer/1640198217)。
|
||||
|
||||
## 操作系统基础
|
||||
|
||||
面试官顶着蓬松的假发向我走来,只见他一手拿着厚重的 Thinkpad ,一手提着他那淡黄的长裙。
|
||||
|
||||
### 什么是操作系统?
|
||||
|
||||
👨💻**面试官** : 先来个简单问题吧!**什么是操作系统?**
|
||||
通过以下四点可以概括操作系统到底是什么:
|
||||
|
||||
🙋 **我** :我通过以下四点向您介绍一下什么是操作系统吧!
|
||||
|
||||
1. **操作系统(Operating System,简称 OS)是管理计算机硬件与软件资源的程序,是计算机的基石。**
|
||||
2. **操作系统本质上是一个运行在计算机上的软件程序 ,用于管理计算机硬件和软件资源。** 举例:运行在你电脑上的所有应用程序都通过操作系统来调用系统内存以及磁盘等等硬件。
|
||||
3. **操作系统存在屏蔽了硬件层的复杂性。** 操作系统就像是硬件使用的负责人,统筹着各种相关事项。
|
||||
4. **操作系统的内核(Kernel)是操作系统的核心部分,它负责系统的内存管理,硬件设备的管理,文件系统的管理以及应用程序的管理**。 内核是连接应用程序和硬件的桥梁,决定着系统的性能和稳定性。
|
||||
1. 操作系统(Operating System,简称 OS)是管理计算机硬件与软件资源的程序,是计算机的基石。
|
||||
2. 操作系统本质上是一个运行在计算机上的软件程序 ,主要用于管理计算机硬件和软件资源。 举例:运行在你电脑上的所有应用程序都通过操作系统来调用系统内存以及磁盘等等硬件。
|
||||
3. 操作系统存在屏蔽了硬件层的复杂性。 操作系统就像是硬件使用的负责人,统筹着各种相关事项。
|
||||
4. 操作系统的内核(Kernel)是操作系统的核心部分,它负责系统的内存管理,硬件设备的管理,文件系统的管理以及应用程序的管理。 内核是连接应用程序和硬件的桥梁,决定着系统的性能和稳定性。
|
||||
|
||||

|
||||
|
||||
### 系统调用
|
||||
### 操作系统主要有哪些功能?
|
||||
|
||||
👨💻**面试官** :**什么是系统调用呢?** 能不能详细介绍一下。
|
||||
从资源管理的角度来看,操作系统有 6 大功能:
|
||||
|
||||
🙋 **我** :介绍系统调用之前,我们先来了解一下用户态和系统态。
|
||||
1. **进程和线程的管理** :进程的创建、撤销、阻塞、唤醒,进程间的通信等。
|
||||
2. **存储管理** :内存的分配和管理、外存(磁盘等)的分配和管理等。
|
||||
3. **文件管理** :文件的读、写、创建及删除等。
|
||||
4. **设备管理** :完成设备(输入输出设备和外部存储设备等)的请求或释放,以及设备启动等功能。
|
||||
5. **网络管理** :操作系统负责管理计算机网络的使用。网络是计算机系统中连接不同计算机的方式,操作系统需要管理计算机网络的配置、连接、通信和安全等,以提供高效可靠的网络服务。
|
||||
6. **安全管理** :用户的身份认证、访问控制、文件加密等,以防止非法用户对系统资源的访问和操作。
|
||||
|
||||
### 用户态和内核态
|
||||
|
||||
#### 什么是用户态和内核态?
|
||||
|
||||
根据进程访问资源的特点,我们可以把进程在系统上的运行分为两个级别:
|
||||
|
||||
1. 用户态(user mode) : 用户态运行的进程可以直接读取用户程序的数据。
|
||||
2. 系统态(kernel mode):可以简单的理解系统态运行的进程或程序几乎可以访问计算机的任何资源,不受限制。
|
||||
- **用户态(User Mode)** : 用户态运行的进程可以直接读取用户程序的数据,拥有较低的权限。当应用程序需要执行某些需要特殊权限的操作,例如读写磁盘、网络通信等,就需要向操作系统发起系统调用请求,进入内核态。
|
||||
- **内核态(Kernel Mode)** :内核态运行的进程几乎可以访问计算机的任何资源包括系统的内存空间、设备、驱动程序等,不受限制,拥有非常高的权限。当操作系统接收到进程的系统调用请求时,就会从用户态切换到内核态,执行相应的系统调用,并将结果返回给进程,最后再从内核态切换回用户态。
|
||||
|
||||
说了用户态和系统态之后,那么什么是系统调用呢?
|
||||

|
||||
|
||||
我们运行的程序基本都是运行在用户态,如果我们调用操作系统提供的系统态级别的子功能咋办呢?那就需要系统调用了!
|
||||
内核态相比用户态拥有更高的特权级别,因此能够执行更底层、更敏感的操作。不过,由于进入内核态需要付出较高的开销(需要进行一系列的上下文切换和权限检查),应该尽量减少进入内核态的次数,以提高系统的性能和稳定性。
|
||||
|
||||
#### 为什么要有用户态和内核态?只有一个内核态不行么?
|
||||
|
||||
- 在 CPU 的所有指令中,有一些指令是比较危险的比如内存分配、设置时钟、IO 处理等,如果所有的程序都能使用这些指令的话,会对系统的正常运行造成灾难性地影响。因此,我们需要限制这些危险指令只能内核态运行。这些只能由操作系统内核态执行的指令也被叫做 **特权指令** 。
|
||||
- 如果计算机系统中只有一个内核态,那么所有程序或进程都必须共享系统资源,例如内存、CPU、硬盘等,这将导致系统资源的竞争和冲突,从而影响系统性能和效率。并且,这样也会让系统的安全性降低,毕竟所有程序或进程都具有相同的特权级别和访问权限。
|
||||
|
||||
因此,同时具有用户态和内核态主要是为了保证计算机系统的安全性、稳定性和性能。
|
||||
|
||||
#### 用户态和内核态是如何切换的?
|
||||
|
||||

|
||||
|
||||
用户态切换到内核态的 3 种方式:
|
||||
|
||||
1. **系统调用(Trap)** :用户态进程 **主动** 要求切换到内核态的一种方式,主要是为了使用内核态才能做的事情比如读取磁盘资源。系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现。
|
||||
2. **中断(Interrupt)** :当外围设备完成用户请求的操作后,会向 CPU 发出相应的中断信号,这时 CPU 会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
|
||||
3. **异常(Exception)**:当 CPU 在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。
|
||||
|
||||
在系统的处理上,中断和异常类似,都是通过中断向量表来找到相应的处理程序进行处理。区别在于,中断来自处理器外部,不是由任何一条专门的指令造成,而异常是执行当前指令的结果。
|
||||
|
||||
### 系统调用
|
||||
|
||||
#### 什么是系统调用?
|
||||
|
||||
我们运行的程序基本都是运行在用户态,如果我们调用操作系统提供的内核态级别的子功能咋办呢?那就需要系统调用了!
|
||||
|
||||
也就是说在我们运行的用户程序中,凡是与系统态级别的资源有关的操作(如文件管理、进程控制、内存管理等),都必须通过系统调用方式向操作系统提出服务请求,并由操作系统代为完成。
|
||||
|
||||

|
||||
|
||||
这些系统调用按功能大致可分为如下几类:
|
||||
|
||||
- 设备管理。完成设备的请求或释放,以及设备启动等功能。
|
||||
- 文件管理。完成文件的读、写、创建及删除等功能。
|
||||
- 进程控制。完成进程的创建、撤销、阻塞及唤醒等功能。
|
||||
- 进程通信。完成进程之间的消息传递或信号传递等功能。
|
||||
- 内存管理。完成内存的分配、回收以及获取作业占用内存区大小及地址等功能。
|
||||
- 设备管理:完成设备(输入输出设备和外部存储设备等)的请求或释放,以及设备启动等功能。
|
||||
- 文件管理:完成文件的读、写、创建及删除等功能。
|
||||
- 进程管理:进程的创建、撤销、阻塞、唤醒,进程间的通信等功能。
|
||||
- 内存管理:完成内存的分配、回收以及获取作业占用内存区大小及地址等功能。
|
||||
|
||||
系统调用和普通库函数调用非常相似,只是系统调用由操作系统内核提供,运行于内核态,而普通的库函数调用由函数库或用户自己提供,运行于用户态。
|
||||
|
||||
总结:系统调用是应用程序与操作系统之间进行交互的一种方式,通过系统调用,应用程序可以访问操作系统底层资源例如文件、设备、网络等。
|
||||
|
||||
#### 系统调用的过程了解吗?
|
||||
|
||||
系统调用的过程可以简单分为以下几个步骤:
|
||||
|
||||
1. 用户态的程序发起系统调用,因为系统调用中涉及一些特权指令(只能由操作系统内核态执行的指令),用户态程序权限不足,因此会中断执行,也就是 Trap(Trap 是一种中断)。
|
||||
2. 发生中断后,当前 CPU 执行的程序会中断,跳转到中断处理程序。内核程序开始执行,也就是开始处理系统调用。
|
||||
3. 内核处理完成后,主动触发 Trap,这样会再次发生中断,切换回用户态工作。
|
||||
|
||||

|
||||
|
||||
## 进程和线程
|
||||
|
||||
### 进程和线程的区别
|
||||
### 什么是进程和线程?
|
||||
|
||||
👨💻**面试官**: 好的!我明白了!那你再说一下: **进程和线程的区别**。
|
||||
- **进程(Process)** 是指计算机中正在运行的一个程序实例。举例:你打开的微信就是一个进程。
|
||||
- **线程(Thread)** 也被称为轻量级进程,更加轻量。多个线程可以在同一个进程中同时执行,并且共享进程的资源比如内存空间、文件句柄、网络连接等。举例:你打开的微信里就有一个线程专门用来拉取别人发你的最新的消息。
|
||||
|
||||
🙋 **我:** 好的! 下图是 Java 内存区域,我们从 JVM 的角度来说一下线程和进程之间的关系吧!
|
||||
### 进程和线程的区别是什么?
|
||||
|
||||
下图是 Java 内存区域,我们从 JVM 的角度来说一下线程和进程之间的关系吧!
|
||||
|
||||

|
||||
|
||||
从上图可以看出:一个进程中可以有多个线程,多个线程共享进程的**堆**和**方法区 (JDK1.8 之后的元空间)**资源,但是每个线程有自己的**程序计数器**、**虚拟机栈** 和 **本地方法栈**。
|
||||
|
||||
**总结:** 线程是进程划分成的更小的运行单位,一个进程在其执行的过程中可以产生多个线程。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。
|
||||
**总结:**
|
||||
|
||||
- 线程是进程划分成的更小的运行单位,一个进程在其执行的过程中可以产生多个线程。
|
||||
- 线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。
|
||||
- 线程执行开销小,但不利于资源的管理和保护;而进程正相反。
|
||||
|
||||
### 有了进程为什么还需要线程?
|
||||
|
||||
- 进程切换是一个开销很大的操作,线程切换的成本较低。
|
||||
- 线程更轻量,一个进程可以创建多个线程。
|
||||
- 多个线程可以并发处理不同的任务,更有效地利用了多处理器和多核计算机。而进程只能在一个时间干一件事,如果在执行过程中遇到阻塞问题比如 IO 阻塞就会挂起直到结果返回。
|
||||
- 同一进程内的线程共享内存和文件,因此它们之间相互通信无须调用内核。
|
||||
|
||||
### 为什么要使用多线程?
|
||||
|
||||
先从总体上来说:
|
||||
|
||||
- **从计算机底层来说:** 线程可以比作是轻量级的进程,是程序执行的最小单位,线程间的切换和调度的成本远远小于进程。另外,多核 CPU 时代意味着多个线程可以同时运行,这减少了线程上下文切换的开销。
|
||||
- **从当代互联网发展趋势来说:** 现在的系统动不动就要求百万级甚至千万级的并发量,而多线程并发编程正是开发高并发系统的基础,利用好多线程机制可以大大提高系统整体的并发能力以及性能。
|
||||
|
||||
再深入到计算机底层来探讨:
|
||||
|
||||
- **单核时代**: 在单核时代多线程主要是为了提高单进程利用 CPU 和 IO 系统的效率。 假设只运行了一个 Java 进程的情况,当我们请求 IO 的时候,如果 Java 进程中只有一个线程,此线程被 IO 阻塞则整个进程被阻塞。CPU 和 IO 设备只有一个在运行,那么可以简单地说系统整体效率只有 50%。当使用多线程的时候,一个线程被 IO 阻塞,其他线程还可以继续使用 CPU。从而提高了 Java 进程利用系统资源的整体效率。
|
||||
- **多核时代**: 多核时代多线程主要是为了提高进程利用多核 CPU 的能力。举个例子:假如我们要计算一个复杂的任务,我们只用一个线程的话,不论系统有几个 CPU 核心,都只会有一个 CPU 核心被利用到。而创建多个线程,这些线程可以被映射到底层多个 CPU 上执行,在任务中的多个线程没有资源竞争的情况下,任务执行的效率会有显著性的提高,约等于(单核时执行时间/CPU 核心数)。
|
||||
|
||||
### 线程间的同步的方式有哪些?
|
||||
|
||||
线程同步是两个或多个共享关键资源的线程的并发执行。应该同步线程以避免关键的资源使用冲突。
|
||||
|
||||
下面是几种常见的线程同步的方式:
|
||||
|
||||
1. **互斥锁(Mutex)**:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。比如 Java 中的 `synchronized` 关键词和各种 `Lock` 都是这种机制。
|
||||
2. **读写锁(Read-Write Lock)**:允许多个线程同时读取共享资源,但只有一个线程可以对共享资源进行写操作。
|
||||
3. **信号量(Semaphore)** :它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。
|
||||
4. **屏障(Barrier)** :屏障是一种同步原语,用于等待多个线程到达某个点再一起继续执行。当一个线程到达屏障时,它会停止执行并等待其他线程到达屏障,直到所有线程都到达屏障后,它们才会一起继续执行。比如 Java 中的 `CyclicBarrier` 是这种机制。
|
||||
5. **事件(Event)** :Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。
|
||||
|
||||
### PCB 是什么?包含哪些信息?
|
||||
|
||||
**PCB(Process Control Block)** 即进程控制块,是操作系统中用来管理和跟踪进程的数据结构,每个进程都对应着一个独立的 PCB。你可以将 PCB 视为进程的大脑。
|
||||
|
||||
当操作系统创建一个新进程时,会为该进程分配一个唯一的进程 ID,并且为该进程创建一个对应的进程控制块。当进程执行时,PCB 中的信息会不断变化,操作系统会根据这些信息来管理和调度进程。
|
||||
|
||||
PCB 主要包含下面几部分的内容:
|
||||
|
||||
- 进程的描述信息,包括进程的名称、标识符等等;
|
||||
- 进程的调度信息,包括进程阻塞原因、进程状态(就绪、运行、阻塞等)、进程优先级(标识进程的重要程度)等等;
|
||||
- 进程对资源的需求情况,包括 CPU 时间、内存空间、I/O 设备等等。
|
||||
- 进程打开的文件信息,包括文件描述符、文件类型、打开模式等等。
|
||||
- 处理机的状态信息(由处理机的各种寄存器中的内容组成的),包括通用寄存器、指令计数器、程序状态字 PSW、用户栈指针。
|
||||
- ......
|
||||
|
||||
### 进程有哪几种状态?
|
||||
|
||||
👨💻**面试官** : 那你再说说**进程有哪几种状态?**
|
||||
|
||||
🙋 **我** :我们一般把进程大致分为 5 种状态,这一点和[线程](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md#6-%E8%AF%B4%E8%AF%B4%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%92%8C%E7%8A%B6%E6%80%81)很像!
|
||||
我们一般把进程大致分为 5 种状态,这一点和线程很像!
|
||||
|
||||
- **创建状态(new)** :进程正在被创建,尚未到就绪状态。
|
||||
- **就绪状态(ready)** :进程已处于准备运行状态,即进程获得了除了处理器之外的一切所需资源,一旦得到处理器资源(处理器分配的时间片)即可运行。
|
||||
@ -95,43 +187,23 @@ head:
|
||||
- **阻塞状态(waiting)** :又称为等待状态,进程正在等待某一事件而暂停运行如等待某资源为可用或等待 IO 操作完成。即使处理器空闲,该进程也不能运行。
|
||||
- **结束状态(terminated)** :进程正在从系统中消失。可能是进程正常结束或其他原因中断退出运行。
|
||||
|
||||
> 订正:下图中 running 状态被 interrupt 向 ready 状态转换的箭头方向反了。
|
||||

|
||||
|
||||

|
||||
|
||||
### 进程间的通信方式
|
||||
|
||||
👨💻**面试官** :**进程间的通信常见的的有哪几种方式呢?**
|
||||
|
||||
🙋 **我** :大概有 7 种常见的进程间的通信方式。
|
||||
### 进程间的通信方式有哪些?
|
||||
|
||||
> 下面这部分总结参考了:[《进程间通信 IPC (InterProcess Communication)》](https://www.jianshu.com/p/c1015f5ffa74) 这篇文章,推荐阅读,总结的非常不错。
|
||||
|
||||
1. **管道/匿名管道(Pipes)** :用于具有亲缘关系的父子进程间或者兄弟进程之间的通信。
|
||||
1. **有名管道(Named Pipes)** : 匿名管道由于没有名字,只能用于亲缘关系的进程间通信。为了克服这个缺点,提出了有名管道。有名管道严格遵循**先进先出(first in first out)**。有名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信。
|
||||
1. **信号(Signal)** :信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生;
|
||||
1. **消息队列(Message Queuing)** :消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识。管道和消息队列的通信数据都是先进先出的原则。与管道(无名管道:只存在于内存中的文件;命名管道:存在于实际的磁盘介质或者文件系统)不同的是消息队列存放在内核中,只有在内核重启(即,操作系统重启)或者显式地删除一个消息队列时,该消息队列才会被真正的删除。消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比 FIFO 更有优势。**消息队列克服了信号承载信息量少,管道只能承载无格式字 节流以及缓冲区大小受限等缺点。**
|
||||
1. **信号量(Semaphores)** :信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步。这种通信方式主要用于解决与同步相关的问题并避免竞争条件。
|
||||
1. **共享内存(Shared memory)** :使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。可以说这是最有用的进程间通信方式。
|
||||
1. **套接字(Sockets)** : 此方法主要用于在客户端和服务器之间通过网络进行通信。套接字是支持 TCP/IP 的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
|
||||
2. **有名管道(Named Pipes)** : 匿名管道由于没有名字,只能用于亲缘关系的进程间通信。为了克服这个缺点,提出了有名管道。有名管道严格遵循**先进先出(first in first out)**。有名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信。
|
||||
3. **信号(Signal)** :信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生;
|
||||
4. **消息队列(Message Queuing)** :消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识。管道和消息队列的通信数据都是先进先出的原则。与管道(无名管道:只存在于内存中的文件;命名管道:存在于实际的磁盘介质或者文件系统)不同的是消息队列存放在内核中,只有在内核重启(即,操作系统重启)或者显式地删除一个消息队列时,该消息队列才会被真正的删除。消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比 FIFO 更有优势。**消息队列克服了信号承载信息量少,管道只能承载无格式字 节流以及缓冲区大小受限等缺点。**
|
||||
5. **信号量(Semaphores)** :信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步。这种通信方式主要用于解决与同步相关的问题并避免竞争条件。
|
||||
6. **共享内存(Shared memory)** :使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。可以说这是最有用的进程间通信方式。
|
||||
7. **套接字(Sockets)** : 此方法主要用于在客户端和服务器之间通过网络进行通信。套接字是支持 TCP/IP 的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
|
||||
|
||||
### 线程间的同步的方式
|
||||
### 进程的调度算法有哪些?
|
||||
|
||||
👨💻**面试官** :**那线程间的同步的方式有哪些呢?**
|
||||
|
||||
🙋 **我** :线程同步是两个或多个共享关键资源的线程的并发执行。应该同步线程以避免关键的资源使用冲突。操作系统一般有下面三种线程同步的方式:
|
||||
|
||||
1. **互斥量(Mutex)**:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。比如 Java 中的 synchronized 关键词和各种 Lock 都是这种机制。
|
||||
1. **信号量(Semaphore)** :它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。
|
||||
1. **事件(Event)** :Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。
|
||||
|
||||
### 进程的调度算法
|
||||
|
||||
👨💻**面试官** :**你知道操作系统中进程的调度算法有哪些吗?**
|
||||
|
||||
🙋 **我** :嗯嗯!这个我们大学的时候学过,是一个很重要的知识点!
|
||||
|
||||
为了确定首先执行哪个进程以及最后执行哪个进程以实现最大 CPU 利用率,计算机科学家已经定义了一些算法,它们是:
|
||||
这是一个很重要的知识点!为了确定首先执行哪个进程以及最后执行哪个进程以实现最大 CPU 利用率,计算机科学家已经定义了一些算法,它们是:
|
||||
|
||||
- **先到先服务(FCFS)调度算法** : 从就绪队列中选择一个最先进入该队列的进程为之分配资源,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用 CPU 时再重新调度。
|
||||
- **短作业优先(SJF)的调度算法** : 从就绪队列中选出一个估计运行时间最短的进程为之分配资源,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用 CPU 时再重新调度。
|
||||
@ -139,22 +211,52 @@ head:
|
||||
- **多级反馈队列调度算法** :前面介绍的几种进程调度的算法都有一定的局限性。如**短进程优先的调度算法,仅照顾了短进程而忽略了长进程** 。多级反馈队列调度算法既能使高优先级的作业得到响应又能使短作业(进程)迅速完成。,因而它是目前**被公认的一种较好的进程调度算法**,UNIX 操作系统采取的便是这种调度算法。
|
||||
- **优先级调度** : 为每个流程分配优先级,首先执行具有最高优先级的进程,依此类推。具有相同优先级的进程以 FCFS 方式执行。可以根据内存要求,时间要求或任何其他资源要求来确定优先级。
|
||||
|
||||
### 什么是死锁
|
||||
### 什么是僵尸进程和孤儿进程?
|
||||
|
||||
👨💻**面试官** :**你知道什么是死锁吗?**
|
||||
在 Unix/Linux 系统中,子进程通常是通过 fork()系统调用创建的,该调用会创建一个新的进程,该进程是原有进程的一个副本。子进程和父进程的运行是相互独立的,它们各自拥有自己的 PCB,即使父进程结束了,子进程仍然可以继续运行。
|
||||
|
||||
🙋 **我** :死锁描述的是这样一种情况:多个进程/线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于进程/线程被无限期地阻塞,因此程序不可能正常终止。
|
||||
当一个进程调用 exit()系统调用结束自己的生命时,内核会释放该进程的所有资源,包括打开的文件、占用的内存等,但是该进程对应的 PCB 依然存在于系统中。这些信息只有在父进程调用 wait()或 waitpid()系统调用时才会被释放,以便让父进程得到子进程的状态信息。
|
||||
|
||||
### 死锁的四个必要条件
|
||||
这样的设计可以让父进程在子进程结束时得到子进程的状态信息,并且可以防止出现“僵尸进程”(即子进程结束后 PCB 仍然存在但父进程无法得到状态信息的情况)。
|
||||
|
||||
👨💻**面试官** :**产生死锁的四个必要条件是什么?**
|
||||
- **僵尸进程 ** :子进程已经终止,但是其父进程仍在运行,且父进程没有调用 wait()或 waitpid()等系统调用来获取子进程的状态信息,释放子进程占用的资源,导致子进程的 PCB 依然存在于系统中,但无法被进一步使用。这种情况下,子进程被称为“僵尸进程”。避免僵尸进程的产生,父进程需要及时调用 wait()或 waitpid()系统调用来回收子进程。
|
||||
- **孤儿进程** :一个进程的父进程已经终止或者不存在,但是该进程仍在运行。这种情况下,该进程就是孤儿进程。孤儿进程通常是由于父进程意外终止或未及时调用 wait()或 waitpid()等系统调用来回收子进程导致的。为了避免孤儿进程占用系统资源,操作系统会将孤儿进程的父进程设置为 init 进程(进程号为 1),由 init 进程来回收孤儿进程的资源。
|
||||
|
||||
🙋 **我** :
|
||||
### 如何查看是否有僵尸进程?
|
||||
|
||||
- **互斥**:资源必须处于非共享模式,即一次只有一个进程可以使用。如果另一进程申请该资源,那么必须等待直到该资源被释放为止。
|
||||
- **占有并等待**:一个进程至少应该占有一个资源,并等待另一资源,而该资源被其他进程所占有。
|
||||
- **非抢占**:资源不能被抢占。只能在持有资源的进程完成任务后,该资源才会被释放。
|
||||
- **循环等待**:有一组等待进程 `{P0, P1,..., Pn}`, `P0` 等待的资源被 `P1` 占有,`P1` 等待的资源被 `P2` 占有,......,`Pn-1` 等待的资源被 `Pn` 占有,`Pn` 等待的资源被 `P0` 占有。
|
||||
Linux 下可以使用 Top 命令查找,`zombie` 值表示僵尸进程的数量,为 0 则代表没有僵尸进程。
|
||||
|
||||

|
||||
|
||||
下面这个命令可以定位僵尸进程以及该僵尸进程的父进程:
|
||||
|
||||
```bash
|
||||
ps -A -ostat,ppid,pid,cmd |grep -e '^[Zz]'
|
||||
```
|
||||
|
||||
## 死锁
|
||||
|
||||
### 什么是死锁?
|
||||
|
||||
死锁(Deadlock)描述的是这样一种情况:多个进程/线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于进程/线程被无限期地阻塞,因此程序不可能正常终止。
|
||||
|
||||
### 能列举一个操作系统发生死锁的例子吗?
|
||||
|
||||
假设有两个进程 A 和 B,以及两个资源 X 和 Y,它们的分配情况如下:
|
||||
|
||||
| 进程 | 占用资源 | 需求资源 |
|
||||
| ---- | -------- | -------- |
|
||||
| A | X | Y |
|
||||
| B | Y | X |
|
||||
|
||||
此时,进程 A 占用资源 X 并且请求资源 Y,而进程 B 已经占用了资源 Y 并请求资源 X。两个进程都在等待对方释放资源,无法继续执行,陷入了死锁状态。
|
||||
|
||||
### 产生死锁的四个必要条件是什么?
|
||||
|
||||
1. **互斥**:资源必须处于非共享模式,即一次只有一个进程可以使用。如果另一进程申请该资源,那么必须等待直到该资源被释放为止。
|
||||
2. **占有并等待**:一个进程至少应该占有一个资源,并等待另一资源,而该资源被其他进程所占有。
|
||||
3. **非抢占**:资源不能被抢占。只能在持有资源的进程完成任务后,该资源才会被释放。
|
||||
4. **循环等待**:有一组等待进程 `{P0, P1,..., Pn}`, `P0` 等待的资源被 `P1` 占有,`P1` 等待的资源被 `P2` 占有,......,`Pn-1` 等待的资源被 `Pn` 占有,`Pn` 等待的资源被 `P0` 占有。
|
||||
|
||||
**注意 ⚠️** :这四个条件是产生死锁的 **必要条件** ,也就是说只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
|
||||
|
||||
@ -162,6 +264,62 @@ head:
|
||||
|
||||
> 如果没有事物情况 A,则必然没有事物情况 B,也就是说如果有事物情况 B 则一定有事物情况 A,那么 A 就是 B 的必要条件。从逻辑学上看,B 能推导出 A,A 就是 B 的必要条件,等价于 B 是 A 的充分条件。
|
||||
|
||||
### 能写一个模拟产生死锁的代码吗?
|
||||
|
||||
下面通过一个实际的例子来模拟下图展示的线程死锁:
|
||||
|
||||

|
||||
|
||||
```java
|
||||
public class DeadLockDemo {
|
||||
private static Object resource1 = new Object();//资源 1
|
||||
private static Object resource2 = new Object();//资源 2
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Thread(() -> {
|
||||
synchronized (resource1) {
|
||||
System.out.println(Thread.currentThread() + "get resource1");
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println(Thread.currentThread() + "waiting get resource2");
|
||||
synchronized (resource2) {
|
||||
System.out.println(Thread.currentThread() + "get resource2");
|
||||
}
|
||||
}
|
||||
}, "线程 1").start();
|
||||
|
||||
new Thread(() -> {
|
||||
synchronized (resource2) {
|
||||
System.out.println(Thread.currentThread() + "get resource2");
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println(Thread.currentThread() + "waiting get resource1");
|
||||
synchronized (resource1) {
|
||||
System.out.println(Thread.currentThread() + "get resource1");
|
||||
}
|
||||
}
|
||||
}, "线程 2").start();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```text
|
||||
Thread[线程 1,5,main]get resource1
|
||||
Thread[线程 2,5,main]get resource2
|
||||
Thread[线程 1,5,main]waiting get resource2
|
||||
Thread[线程 2,5,main]waiting get resource1
|
||||
```
|
||||
|
||||
线程 A 通过 `synchronized (resource1)` 获得 `resource1` 的监视器锁,然后通过`Thread.sleep(1000);`让线程 A 休眠 1s 为的是让线程 B 得到执行然后获取到 `resource2` 的监视器锁。线程 A 和线程 B 休眠结束了都开始企图请求获取对方的资源,然后这两个线程就会陷入互相等待的状态,这也就产生了死锁。
|
||||
|
||||
### 解决死锁的方法
|
||||
|
||||
解决死锁的方法可以从多个角度去分析,一般的情况下,有**预防,避免,检测和解除四种**。
|
||||
@ -244,206 +402,11 @@ head:
|
||||
3. **逐个撤销涉及死锁的进程,回收其资源直至死锁解除。**
|
||||
4. **抢占资源** :从涉及死锁的一个或几个进程中抢占资源,把夺得的资源再分配给涉及死锁的进程直至死锁解除。
|
||||
|
||||
## 操作系统内存管理基础
|
||||
|
||||
### 内存管理介绍
|
||||
|
||||
👨💻 **面试官**: **操作系统的内存管理主要是做什么?**
|
||||
|
||||
🙋 **我:** 操作系统的内存管理主要负责内存的分配与回收(malloc 函数:申请内存,free 函数:释放内存),另外地址转换也就是将逻辑地址转换成相应的物理地址等功能也是操作系统内存管理做的事情。
|
||||
|
||||
### 常见的几种内存管理机制
|
||||
|
||||
👨💻 **面试官**: **操作系统的内存管理机制了解吗?内存管理有哪几种方式?**
|
||||
|
||||
🙋 **我:** 这个在学习操作系统的时候有了解过。
|
||||
|
||||
简单分为**连续分配管理方式**和**非连续分配管理方式**这两种。连续分配管理方式是指为一个用户程序分配一个连续的内存空间,常见的如 **块式管理** 。同样地,非连续分配管理方式允许一个程序使用的内存分布在离散或者说不相邻的内存中,常见的如**页式管理** 和 **段式管理**。
|
||||
|
||||
1. **块式管理** : 远古时代的计算机操作系统的内存管理方式。将内存分为几个固定大小的块,每个块中只包含一个进程。如果程序运行需要内存的话,操作系统就分配给它一块,如果程序运行只需要很小的空间的话,分配的这块内存很大一部分几乎被浪费了。这些在每个块中未被利用的空间,我们称之为碎片。
|
||||
2. **页式管理** :把主存分为大小相等且固定的一页一页的形式,页较小,相比于块式管理的划分粒度更小,提高了内存利用率,减少了碎片。页式管理通过页表对应逻辑地址和物理地址。
|
||||
3. **段式管理** : 页式管理虽然提高了内存利用率,但是页式管理其中的页并无任何实际意义。 段式管理把主存分为一段段的,段是有实际意义的,每个段定义了一组逻辑信息,例如,有主程序段 MAIN、子程序段 X、数据段 D 及栈段 S 等。 段式管理通过段表对应逻辑地址和物理地址。
|
||||
|
||||
简单来说:页是物理单位,段是逻辑单位。分页可以有效提高内存利用率,分段可以更好满足用户需求。
|
||||
|
||||
👨💻**面试官** : 回答的还不错!不过漏掉了一个很重要的 **段页式管理机制** 。段页式管理机制结合了段式管理和页式管理的优点。简单来说段页式管理机制就是把主存先分成若干段,每个段又分成若干页,也就是说 **段页式管理机制** 中段与段之间以及段的内部的都是离散的。
|
||||
|
||||
🙋 **我** :谢谢面试官!刚刚把这个给忘记了~
|
||||
|
||||
### 快表和多级页表
|
||||
|
||||
👨💻**面试官** : 页表管理机制中有两个很重要的概念:快表和多级页表,这两个东西分别解决了页表管理中很重要的两个问题。你给我简单介绍一下吧!
|
||||
|
||||
🙋 **我** :在分页内存管理中,很重要的两点是:
|
||||
|
||||
1. 虚拟地址到物理地址的转换要快。
|
||||
2. 解决虚拟地址空间大,页表也会很大的问题。
|
||||
|
||||
#### 快表
|
||||
|
||||
为了提高虚拟地址到物理地址的转换速度,操作系统在 **页表方案** 基础之上引入了 **快表** 来加速虚拟地址到物理地址的转换。我们可以把快表理解为一种特殊的高速缓冲存储器(Cache),其中的内容是页表的一部分或者全部内容。作为页表的 Cache,它的作用与页表相似,但是提高了访问速率。由于采用页表做地址转换,读写内存数据时 CPU 要访问两次主存。有了快表,有时只要访问一次高速缓冲存储器,一次主存,这样可加速查找并提高指令执行速度。
|
||||
|
||||
使用快表之后的地址转换流程是这样的:
|
||||
|
||||
1. 根据虚拟地址中的页号查快表;
|
||||
2. 如果该页在快表中,直接从快表中读取相应的物理地址;
|
||||
3. 如果该页不在快表中,就访问内存中的页表,再从页表中得到物理地址,同时将页表中的该映射表项添加到快表中;
|
||||
4. 当快表填满后,又要登记新页时,就按照一定的淘汰策略淘汰掉快表中的一个页。
|
||||
|
||||
看完了之后你会发现快表和我们平时经常在开发系统中使用的缓存(比如 Redis)很像,的确是这样的,操作系统中的很多思想、很多经典的算法,你都可以在我们日常开发使用的各种工具或者框架中找到它们的影子。
|
||||
|
||||
#### 多级页表
|
||||
|
||||
引入多级页表的主要目的是为了避免把全部页表一直放在内存中占用过多空间,特别是那些根本就不需要的页表就不需要保留在内存中。
|
||||
|
||||
多级页表属于时间换空间的典型场景。
|
||||
|
||||
#### 总结
|
||||
|
||||
为了提高内存的空间性能,提出了多级页表的概念;但是提到空间性能是以浪费时间性能为基础的,因此为了补充损失的时间性能,提出了快表(即 TLB)的概念。 不论是快表还是多级页表实际上都利用到了程序的局部性原理,局部性原理在后面的虚拟内存这部分会介绍到。
|
||||
|
||||
### 分页机制和分段机制的共同点和区别
|
||||
|
||||
👨💻**面试官** : **分页机制和分段机制有哪些共同点和区别呢?**
|
||||
|
||||
🙋 **我** :
|
||||
|
||||
1. **共同点** :
|
||||
- 分页机制和分段机制都是为了提高内存利用率,减少内存碎片。
|
||||
- 页和段都是离散存储的,所以两者都是离散分配内存的方式。但是,每个页和段中的内存是连续的。
|
||||
2. **区别** :
|
||||
- 页的大小是固定的,由操作系统决定;而段的大小不固定,取决于我们当前运行的程序。
|
||||
- 分页仅仅是为了满足操作系统内存管理的需求,而段是逻辑信息的单位,在程序中可以体现为代码段,数据段,能够更好满足用户的需要。
|
||||
|
||||
### 逻辑(虚拟)地址和物理地址
|
||||
|
||||
👨💻**面试官** :你刚刚还提到了**逻辑地址和物理地址**这两个概念,我不太清楚,你能为我解释一下不?
|
||||
|
||||
🙋 **我:** em...好的嘛!我们编程一般只有可能和逻辑地址打交道,比如在 C 语言中,指针里面存储的数值就可以理解成为内存里的一个地址,这个地址也就是我们说的逻辑地址,逻辑地址由操作系统决定。物理地址指的是真实物理内存中地址,更具体一点来说就是内存地址寄存器中的地址。物理地址是内存单元真正的地址。
|
||||
|
||||
### CPU 寻址了解吗?为什么需要虚拟地址空间?
|
||||
|
||||
👨💻**面试官** :**CPU 寻址了解吗?为什么需要虚拟地址空间?**
|
||||
|
||||
🙋 **我** :这部分我真不清楚!
|
||||
|
||||
于是面试完之后我默默去查阅了相关文档!留下了没有技术的泪水。。。
|
||||
|
||||
> 这部分内容参考了 Microsoft 官网的介绍,地址:<https://docs.microsoft.com/zh-cn/windows-hardware/drivers/gettingstarted/virtual-address-spaces?redirectedfrom=MSDN>
|
||||
|
||||
现代处理器使用的是一种称为 **虚拟寻址(Virtual Addressing)** 的寻址方式。**使用虚拟寻址,CPU 需要将虚拟地址翻译成物理地址,这样才能访问到真实的物理内存。** 实际上完成虚拟地址转换为物理地址的硬件是 CPU 中含有一个被称为 **内存管理单元(Memory Management Unit, MMU)** 的硬件。如下图所示:
|
||||
|
||||

|
||||
|
||||
**为什么要有虚拟地址空间呢?**
|
||||
|
||||
先从没有虚拟地址空间的时候说起吧!没有虚拟地址空间的时候,**程序直接访问和操作的都是物理内存** 。但是这样有什么问题呢?
|
||||
|
||||
1. 用户程序可以访问任意内存,寻址内存的每个字节,这样就很容易(有意或者无意)破坏操作系统,造成操作系统崩溃。
|
||||
2. 想要同时运行多个程序特别困难,比如你想同时运行一个微信和一个 QQ 音乐都不行。为什么呢?举个简单的例子:微信在运行的时候给内存地址 1xxx 赋值后,QQ 音乐也同样给内存地址 1xxx 赋值,那么 QQ 音乐对内存的赋值就会覆盖微信之前所赋的值,这就造成微信这个程序会崩溃。
|
||||
|
||||
**总结来说:如果直接把物理地址暴露出来的话会带来严重问题,比如可能对操作系统造成伤害以及给同时运行多个程序造成困难。**
|
||||
|
||||
通过虚拟地址访问内存有以下优势:
|
||||
|
||||
- 程序可以使用一系列相邻的虚拟地址来访问物理内存中不相邻的大内存缓冲区。
|
||||
- 程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,内存管理器会将物理内存页(通常大小为 4 KB)保存到磁盘文件。数据或代码页会根据需要在物理内存与磁盘之间移动。
|
||||
- 不同进程使用的虚拟地址彼此隔离。一个进程中的代码无法更改正在由另一进程或操作系统使用的物理内存。
|
||||
|
||||
## 虚拟内存
|
||||
|
||||
### 什么是虚拟内存(Virtual Memory)?
|
||||
|
||||
👨💻**面试官** :再问你一个常识性的问题!**什么是虚拟内存(Virtual Memory)?**
|
||||
|
||||
🙋 **我** :这个在我们平时使用电脑特别是 Windows 系统的时候太常见了。很多时候我们使用了很多占内存的软件,这些软件占用的内存可能已经远远超出了我们电脑本身具有的物理内存。**为什么可以这样呢?** 正是因为 **虚拟内存** 的存在,通过 **虚拟内存** 可以让程序拥有超过系统物理内存大小的可用内存空间。另外,**虚拟内存为每个进程提供了一个一致的、私有的地址空间,它让每个进程产生了一种自己在独享主存的错觉(每个进程拥有一片连续完整的内存空间)**。这样会更加有效地管理内存并减少出错。
|
||||
|
||||
**虚拟内存**是计算机系统内存管理的一种技术,我们可以手动设置自己电脑的虚拟内存。不要单纯认为虚拟内存只是“使用硬盘空间来扩展内存“的技术。**虚拟内存的重要意义是它定义了一个连续的虚拟地址空间**,并且 **把内存扩展到硬盘空间**。推荐阅读:[《虚拟内存的那点事儿》](https://juejin.im/post/59f8691b51882534af254317)
|
||||
|
||||
维基百科中有几句话是这样介绍虚拟内存的。
|
||||
|
||||
> **虚拟内存** 使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。与没有使用虚拟内存技术的系统相比,使用这种技术的系统使得大型程序的编写变得更容易,对真正的物理内存(例如 RAM)的使用也更有效率。目前,大多数操作系统都使用了虚拟内存,如 Windows 家族的“虚拟内存”;Linux 的“交换空间”等。From:<https://zh.wikipedia.org/wiki/虚拟内存>
|
||||
|
||||
### 局部性原理
|
||||
|
||||
👨💻**面试官** :要想更好地理解虚拟内存技术,必须要知道计算机中著名的**局部性原理**。另外,局部性原理既适用于程序结构,也适用于数据结构,是非常重要的一个概念。
|
||||
|
||||
🙋 **我** :局部性原理是虚拟内存技术的基础,正是因为程序运行具有局部性原理,才可以只装入部分程序到内存就开始运行。
|
||||
|
||||
> 以下内容摘自《计算机操作系统教程》 第 4 章存储器管理。
|
||||
|
||||
早在 1968 年的时候,就有人指出我们的程序在执行的时候往往呈现局部性规律,也就是说在某个较短的时间段内,程序执行局限于某一小部分,程序访问的存储空间也局限于某个区域。
|
||||
|
||||
局部性原理表现在以下两个方面:
|
||||
|
||||
1. **时间局部性** :如果程序中的某条指令一旦执行,不久以后该指令可能再次执行;如果某数据被访问过,不久以后该数据可能再次被访问。产生时间局部性的典型原因,是由于在程序中存在着大量的循环操作。
|
||||
2. **空间局部性** :一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也将被访问,即程序在一段时间内所访问的地址,可能集中在一定的范围之内,这是因为指令通常是顺序存放、顺序执行的,数据也一般是以向量、数组、表等形式簇聚存储的。
|
||||
|
||||
时间局部性是通过将近来使用的指令和数据保存到高速缓存存储器中,并使用高速缓存的层次结构实现。空间局部性通常是使用较大的高速缓存,并将预取机制集成到高速缓存控制逻辑中实现。虚拟内存技术实际上就是建立了 “内存一外存”的两级存储器的结构,利用局部性原理实现髙速缓存。
|
||||
|
||||
### 虚拟存储器
|
||||
|
||||
> **勘误:虚拟存储器又叫做虚拟内存,都是 Virtual Memory 的翻译,属于同一个概念。**
|
||||
|
||||
👨💻**面试官** :~~都说了虚拟内存了。你再讲讲**虚拟存储器**把!~~
|
||||
|
||||
🙋 **我** :
|
||||
|
||||
> 这部分内容来自:[王道考研操作系统知识点整理](https://wizardforcel.gitbooks.io/wangdaokaoyan-os/content/13.html)。
|
||||
|
||||
基于局部性原理,在程序装入时,可以将程序的一部分装入内存,而将其他部分留在外存,就可以启动程序执行。由于外存往往比内存大很多,所以我们运行的软件的内存大小实际上是可以比计算机系统实际的内存大小大的。在程序执行过程中,当所访问的信息不在内存时,由操作系统将所需要的部分调入内存,然后继续执行程序。另一方面,操作系统将内存中暂时不使用的内容换到外存上,从而腾出空间存放将要调入内存的信息。这样,计算机好像为用户提供了一个比实际内存大得多的存储器——**虚拟存储器**。
|
||||
|
||||
实际上,我觉得虚拟内存同样是一种时间换空间的策略,你用 CPU 的计算时间,页的调入调出花费的时间,换来了一个虚拟的更大的空间来支持程序的运行。不得不感叹,程序世界几乎不是时间换空间就是空间换时间。
|
||||
|
||||
### 虚拟内存的技术实现
|
||||
|
||||
👨💻**面试官** :**虚拟内存技术的实现呢?**
|
||||
|
||||
🙋 **我** :**虚拟内存的实现需要建立在离散分配的内存管理方式的基础上。** 虚拟内存的实现有以下三种方式:
|
||||
|
||||
1. **请求分页存储管理** :建立在分页管理之上,为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能。请求分页是目前最常用的一种实现虚拟存储器的方法。请求分页存储管理系统中,在作业开始运行之前,仅装入当前要执行的部分段即可运行。假如在作业运行的过程中发现要访问的页面不在内存,则由处理器通知操作系统按照对应的页面置换算法将相应的页面调入到主存,同时操作系统也可以将暂时不用的页面置换到外存中。
|
||||
2. **请求分段存储管理** :建立在分段存储管理之上,增加了请求调段功能、分段置换功能。请求分段储存管理方式就如同请求分页储存管理方式一样,在作业开始运行之前,仅装入当前要执行的部分段即可运行;在执行过程中,可使用请求调入中断动态装入要访问但又不在内存的程序段;当内存空间已满,而又需要装入新的段时,根据置换功能适当调出某个段,以便腾出空间而装入新的段。
|
||||
3. **请求段页式存储管理**
|
||||
|
||||
**这里多说一下?很多人容易搞混请求分页与分页存储管理,两者有何不同呢?**
|
||||
|
||||
请求分页存储管理建立在分页管理之上。他们的根本区别是是否将程序所需的全部地址空间都装入主存,这也是请求分页存储管理可以提供虚拟内存的原因,我们在上面已经分析过了。
|
||||
|
||||
它们之间的根本区别在于是否将一作业的全部地址空间同时装入主存。请求分页存储管理不要求将作业全部地址空间同时装入主存。基于这一点,请求分页存储管理可以提供虚存,而分页存储管理却不能提供虚存。
|
||||
|
||||
不管是上面那种实现方式,我们一般都需要:
|
||||
|
||||
1. 一定容量的内存和外存:在载入程序的时候,只需要将程序的一部分装入内存,而将其他部分留在外存,然后程序就可以执行了;
|
||||
2. **缺页中断**:如果**需执行的指令或访问的数据尚未在内存**(称为缺页或缺段),则由处理器通知操作系统将相应的页面或段**调入到内存**,然后继续执行程序;
|
||||
3. **虚拟地址空间** :逻辑地址到物理地址的变换。
|
||||
|
||||
### 页面置换算法
|
||||
|
||||
👨💻**面试官** :虚拟内存管理很重要的一个概念就是页面置换算法。那你说一下 **页面置换算法的作用?常见的页面置换算法有哪些?**
|
||||
|
||||
🙋 **我** :
|
||||
|
||||
> 这个题目经常作为笔试题出现,网上已经给出了很不错的回答,我这里只是总结整理了一下。
|
||||
|
||||
地址映射过程中,若在页面中发现所要访问的页面不在内存中,则发生缺页中断 。
|
||||
|
||||
> **缺页中断** 就是要访问的**页**不在主存,需要操作系统将其调入主存后再进行访问。 在这个时候,被内存映射的文件实际上成了一个分页交换文件。
|
||||
|
||||
当发生缺页中断时,如果当前内存中并没有空闲的页面,操作系统就必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。用来选择淘汰哪一页的规则叫做页面置换算法,我们可以把页面置换算法看成是淘汰页面的规则。
|
||||
|
||||
- **OPT 页面置换算法(最佳页面置换算法)** :最佳(Optimal, OPT)置换算法所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。但由于人们目前无法预知进程在内存下的若千页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现。一般作为衡量其他置换算法的方法。
|
||||
- **FIFO(First In First Out) 页面置换算法(先进先出页面置换算法)** : 总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面进行淘汰。
|
||||
- **LRU (Least Recently Used)页面置换算法(最近最久未使用页面置换算法)** :LRU 算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 T,当须淘汰一个页面时,选择现有页面中其 T 值最大的,即最近最久未使用的页面予以淘汰。
|
||||
- **LFU (Least Frequently Used)页面置换算法(最少使用页面置换算法)** : 该置换算法选择在之前时期使用最少的页面作为淘汰页。
|
||||
|
||||
## 参考
|
||||
|
||||
- 《计算机操作系统—汤小丹》第四版
|
||||
- [《深入理解计算机系统》](https://book.douban.com/subject/1230413/)
|
||||
- [https://zh.wikipedia.org/wiki/输入输出内存管理单元](https://zh.wikipedia.org/wiki/输入输出内存管理单元)
|
||||
- [https://baike.baidu.com/item/快表/19781679](https://baike.baidu.com/item/快表/19781679)
|
||||
- https://www.jianshu.com/p/1d47ed0b46d5
|
||||
- <https://www.studytonight.com/operating-system>
|
||||
- <https://www.geeksforgeeks.org/interprocess-communication-methods/>
|
||||
- <https://juejin.im/post/59f8691b51882534af254317>
|
||||
- 王道考研操作系统知识点整理: https://wizardforcel.gitbooks.io/wangdaokaoyan-os/content/13.html
|
||||
- 《深入理解计算机系统》
|
||||
- 《重学操作系统》
|
||||
- 操作系统为什么要分用户态和内核态:https://blog.csdn.net/chen134225/article/details/81783980
|
||||
- 从根上理解用户态与内核态:https://juejin.cn/post/6923863670132850701
|
||||
- 什么是僵尸进程与孤儿进程:https://blog.csdn.net/a745233700/article/details/120715371
|
||||
|
@ -214,7 +214,7 @@ SELECT id FROM table WHERE id=1;
|
||||
|
||||
### 覆盖索引
|
||||
|
||||
如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为 **覆盖索引(Covering Index)** 。我们知道在 InnoDB 存储引擎中,如果不是主键索引,叶子节点存储的是主键+列值。最终还是要“回表”,也就是要通过主键再查找一次。这样就会比较慢覆盖索引就是把要查询出的列和索引是对应的,不做回表操作!
|
||||
如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为 **覆盖索引(Covering Index)** 。我们知道在 InnoDB 存储引擎中,如果不是主键索引,叶子节点存储的是主键+列值。最终还是要“回表”,也就是要通过主键再查找一次,这样就会比较慢。而覆盖索引就是把要查询出的列和索引是对应的,不做回表操作!
|
||||
|
||||
**覆盖索引即需要查询的字段正好是索引的字段,那么直接根据该索引,就可以查到数据了,而无需回表查询。**
|
||||
|
||||
|
@ -517,7 +517,7 @@ SELECT ... FOR UPDATE;
|
||||
- **意向共享锁(Intention Shared Lock,IS 锁)**:事务有意向对表中的某些记录加共享锁(S 锁),加共享锁前必须先取得该表的 IS 锁。
|
||||
- **意向排他锁(Intention Exclusive Lock,IX 锁)**:事务有意向对表中的某些记录加排他锁(X 锁),加排他锁之前必须先取得该表的 IX 锁。
|
||||
|
||||
**意向锁是有数据引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享/排他锁之前,InooDB 会先获取该数据行所在在数据表的对应意向锁。**
|
||||
**意向锁是由数据引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享/排他锁之前,InooDB 会先获取该数据行所在在数据表的对应意向锁。**
|
||||
|
||||
意向锁之间是互相兼容的。
|
||||
|
||||
|
@ -526,6 +526,8 @@ System.out.println(s);
|
||||
|
||||
如果你使用 IDEA 的话,IDEA 自带的代码检查机制也会提示你修改代码。
|
||||
|
||||
不过,使用 “+” 进行字符串拼接会产生大量的临时对象的问题在 JDK9 中得到了解决。在 JDK9 当中,字符串相加 “+” 改为了用动态方法 `makeConcatWithConstants()` 来实现,而不是大量的 `StringBuilder` 了。这个改进是 JDK9 的 [JEP 280](https://openjdk.org/jeps/280) 提出的,这也意味着 JDK 9 之后,你可以放心使用“+” 进行字符串拼接了。关于这部分改进的详细介绍,推荐阅读这篇文章:还在无脑用 [StringBuilder?来重温一下字符串拼接吧](https://juejin.cn/post/7182872058743750715) 。
|
||||
|
||||
#### String#equals() 和 Object#equals() 有何区别?
|
||||
|
||||
`String` 中的 `equals` 方法是被重写过的,比较的是 String 字符串的值是否相等。 `Object` 的 `equals` 方法是比较的对象的内存地址。
|
||||
|
@ -157,7 +157,7 @@ Java 线程状态变迁图(图源:[挑错 |《Java 并发编程的艺术》中
|
||||
|
||||
相关阅读:[线程的几种状态你真的了解么?](https://mp.weixin.qq.com/s/R5MrTsWvk9McFSQ7bS0W2w) 。
|
||||
|
||||
## 什么是上下文切换?
|
||||
## 什么是线程上下文切换?
|
||||
|
||||
线程在执行过程中会有自己的运行条件和状态(也称上下文),比如上文所说到过的程序计数器,栈信息等。当出现如下情况的时候,线程会从占用 CPU 状态中退出。
|
||||
|
||||
|
@ -403,15 +403,16 @@ public class SynchronizedDemo {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
通过 JDK 自带的 `javap` 命令查看 `SynchronizedDemo` 类的相关字节码信息:首先切换到类的对应目录执行 `javac SynchronizedDemo.java` 命令生成编译后的 .class 文件,然后执行`javap -c -s -v -l SynchronizedDemo.class`。
|
||||
|
||||

|
||||

|
||||
|
||||
从上面我们可以看出:**`synchronized` 同步语句块的实现使用的是 `monitorenter` 和 `monitorexit` 指令,其中 `monitorenter` 指令指向同步代码块的开始位置,`monitorexit` 指令则指明同步代码块的结束位置。**
|
||||
|
||||
上面的字节码中包含一个 `monitorenter` 指令以及两个 `monitorexit` 指令,这是为了保证锁在同步代码块代码正常执行以及出现异常的这两种情况下都能被正确释放。
|
||||
|
||||
当执行 `monitorenter` 指令时,线程试图获取锁也就是获取 **对象监视器 `monitor`** 的持有权。
|
||||
|
||||
> 在 Java 虚拟机(HotSpot)中,Monitor 是基于 C++实现的,由[ObjectMonitor](https://github.com/openjdk-mirror/jdk7u-hotspot/blob/50bdefc3afe944ca74c3093e7448d6b889cd20d1/src/share/vm/runtime/objectMonitor.cpp)实现的。每个对象中都内置了一个 `ObjectMonitor`对象。
|
||||
|
@ -193,8 +193,6 @@ CPU 密集型简单理解就是利用 CPU 计算能力的任务比如你在内
|
||||
|
||||

|
||||
|
||||
还没看够?推荐 why 神的[《如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答。》](https://mp.weixin.qq.com/s/9HLuPcoWmTqAeFKa1kj-_A)这篇文章,深度剖析,很不错哦!
|
||||
|
||||
如果我们的项目也想要实现这种效果的话,可以借助现成的开源项目:
|
||||
|
||||
- **[Hippo-4](https://github.com/opengoofy/hippo4j)** :一款强大的动态线程池框架,解决了传统线程池使用存在的一些痛点比如线程池参数没办法动态修改、不支持运行时变量的传递、无法执行优雅关闭。除了支持动态修改线程池参数、线程池任务传递上下文,还支持通知报警、运行监控等开箱即用的功能。
|
||||
|
@ -440,7 +440,7 @@ JDK1.8 默认使用的是 Parallel Scavenge + Parallel Old,如果指定了-XX:
|
||||
- **并行与并发**:G1 能充分利用 CPU、多核环境下的硬件优势,使用多个 CPU(CPU 或者 CPU 核心)来缩短 Stop-The-World 停顿时间。部分其他收集器原本需要停顿 Java 线程执行的 GC 动作,G1 收集器仍然可以通过并发的方式让 java 程序继续执行。
|
||||
- **分代收集**:虽然 G1 可以不需要其他收集器配合就能独立管理整个 GC 堆,但是还是保留了分代的概念。
|
||||
- **空间整合**:与 CMS 的“标记-清除”算法不同,G1 从整体来看是基于“标记-整理”算法实现的收集器;从局部上来看是基于“标记-复制”算法实现的。
|
||||
- **可预测的停顿**:这是 G1 相对于 CMS 的另一个大优势,降低停顿时间是 G1 和 CMS 共同的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内。
|
||||
- **可预测的停顿**:这是 G1 相对于 CMS 的另一个大优势,降低停顿时间是 G1 和 CMS 共同的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间不得超过 N 毫秒。
|
||||
|
||||
G1 收集器的运作大致分为以下几个步骤:
|
||||
|
||||
|
@ -252,7 +252,7 @@ JDK1.7 之前,字符串常量池存放在永久代。JDK1.7 字符串常量池
|
||||
|
||||
直接内存并不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用。而且也可能导致 `OutOfMemoryError` 错误出现。
|
||||
|
||||
JDK1.4 中新加入的 **NIO(New Input/Output) 类**,引入了一种基于**通道(Channel)**与**缓存区(Buffer)**的 I/O 方式,它可以直接使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样就能在一些场景中显著提高性能,因为**避免了在 Java 堆和 Native 堆之间来回复制数据**。
|
||||
JDK1.4 中新加入的 **NIO(Non-Blocking I/O,也被称为New I/O)**,引入了一种基于**通道(Channel)**与**缓存区(Buffer)**的 I/O 方式,它可以直接使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样就能在一些场景中显著提高性能,因为**避免了在 Java 堆和 Native 堆之间来回复制数据**。
|
||||
|
||||
直接内存的分配不会受到 Java 堆的限制,但是,既然是内存就会受到本机总内存大小以及处理器寻址空间的限制。
|
||||
|
||||
|
@ -31,6 +31,8 @@ tag:
|
||||
|
||||
万一在这两个操作之间突然出现错误比如银行系统崩溃或者网络故障,导致小明余额减少而小红的余额没有增加,这样就不对了。事务就是保证这两个关键操作要么都成功,要么都要失败。
|
||||
|
||||

|
||||
|
||||
```java
|
||||
public class OrdersService {
|
||||
private AccountDao accountDao;
|
||||
@ -57,12 +59,22 @@ public class OrdersService {
|
||||
|
||||
## 事务的特性(ACID)了解么?
|
||||
|
||||
- **原子性(Atomicity):** 一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。
|
||||
- **一致性(Consistency):** 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
|
||||
- **隔离性(Isolation):** 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括未提交读(Read uncommitted)、提交读(read committed)、可重复读(repeatable read)和串行化(Serializable)。
|
||||
- **持久性(Durability):** 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
|
||||
1. **原子性**(`Atomicity`) : 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
|
||||
2. **一致性**(`Consistency`): 执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
|
||||
3. **隔离性**(`Isolation`): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
|
||||
4. **持久性**(`Durability`): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
|
||||
|
||||
参考 :[https://zh.wikipedia.org/wiki/ACID](https://zh.wikipedia.org/wiki/ACID) 。
|
||||
🌈 这里要额外补充一点:**只有保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。也就是说 A、I、D 是手段,C 是目的!** 想必大家也和我一样,被 ACID 这个概念被误导了很久! 我也是看周志明老师的公开课[《周志明的软件架构课》](https://time.geekbang.org/opencourse/intro/100064201)才搞清楚的(多看好书!!!)。
|
||||
|
||||

|
||||
|
||||
另外,DDIA 也就是 [《Designing Data-Intensive Application(数据密集型应用系统设计)》](https://book.douban.com/subject/30329536/) 的作者在他的这本书中如是说:
|
||||
|
||||
> Atomicity, isolation, and durability are properties of the database, whereas consis‐ tency (in the ACID sense) is a property of the application. The application may rely on the database’s atomicity and isolation properties in order to achieve consistency, but it’s not up to the database alone.
|
||||
>
|
||||
> 翻译过来的意思是:原子性,隔离性和持久性是数据库的属性,而一致性(在 ACID 意义上)是应用程序的属性。应用可能依赖数据库的原子性和隔离属性来实现一致性,但这并不仅取决于数据库。因此,字母 C 不属于 ACID 。
|
||||
|
||||
《Designing Data-Intensive Application(数据密集型应用系统设计)》这本书强推一波,值得读很多遍!豆瓣有接近 90% 的人看了这本书之后给了五星好评。另外,中文翻译版本已经在 Github 开源,地址:[https://github.com/Vonng/ddiaopen in new window](https://github.com/Vonng/ddia) 。
|
||||
|
||||
## 详谈 Spring 对事务的支持
|
||||
|
||||
@ -190,8 +202,8 @@ public interface PlatformTransactionManager {
|
||||
>
|
||||
> 举个例子,我上个项目有发送短信的需求,为此,我们定了一个接口,接口只有两个方法:
|
||||
>
|
||||
> 1.发送短信
|
||||
> 2.处理发送结果的方法。
|
||||
> 1.发送短信
|
||||
> 2.处理发送结果的方法。
|
||||
>
|
||||
> 刚开始我们用的是阿里云短信服务,然后我们实现这个接口完成了一个阿里云短信的服务。后来,我们突然又换到了别的短信服务平台,我们这个时候只需要再实现这个接口即可。这样保证了我们提供给外部的行为不变。几乎不需要改变什么代码,我们就轻松完成了需求的转变,提高了代码的灵活性和可扩展性。
|
||||
>
|
||||
@ -411,7 +423,7 @@ Class B {
|
||||
|
||||
如果当前存在事务,就在嵌套事务内执行;如果当前没有事务,就执行与`TransactionDefinition.PROPAGATION_REQUIRED`类似的操作。也就是说:
|
||||
|
||||
- 在外部方法开启事务的情况下,在内部开启一个新的事务,作为嵌套事务存在。
|
||||
- 在外部方法开启事务的情况下,在内部开启一个新的事务,作为嵌套事务存在。
|
||||
- 如果外部方法无事务,则单独开启一个事务,与 `PROPAGATION_REQUIRED` 类似。
|
||||
|
||||
这里还是简单举个例子:如果 `bMethod()` 回滚的话,`aMethod()`不会回滚。如果 `aMethod()` 回滚的话,`bMethod()`会回滚。
|
||||
@ -686,4 +698,3 @@ private void method1() {
|
||||
- Spring 事务的传播特性:[https://github.com/love-somnus/Spring/wiki/Spring 事务的传播特性](https://github.com/love-somnus/Spring/wiki/Spring事务的传播特性)
|
||||
- [Spring 事务传播行为详解](https://segmentfault.com/a/1190000013341344) :[https://segmentfault.com/a/1190000013341344](https://segmentfault.com/a/1190000013341344)
|
||||
- 全面分析 Spring 的编程式事务管理及声明式事务管理:[https://www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/index.html](https://www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/index.html)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user