├── .idea
├── .gitignore
├── checkstyle-idea.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── LICENSE
├── README.md
├── dockerNotes
└── docker必知必会.md
├── java virtual machine
└── JVM虚拟机.md
├── leetcode
└── Leetcode 题解刷题顺序.md
├── network of computer
└── 计算机网络.md
├── open source project learning method
└── 开源项目学习.md
├── operation system
└── 操作系统.md
├── 刷题册.md
├── 小曾Linux私房菜.pdf
├── 常用命令合集.pdf
├── 操作系统查漏补缺.md
├── 数据库查漏补缺.md
├── 注解开发笔记.pdf
└── 计算机网络查漏补缺.md
/.idea/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzzzzzzzyt/JavaLearningNotes/d53263b10ab6655900423e19437efb3936f4a223/.idea/.gitignore
--------------------------------------------------------------------------------
/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | C:\Users\asus\AppData\Roaming\Subversion
84 |
85 |
86 |
87 |
88 |
89 |
90 | 1642382313276
91 |
92 |
93 | 1642382313276
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
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 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
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 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 | 1668405408708
546 |
547 |
548 |
549 | 1668405408708
550 |
551 |
552 | 1668472640752
553 |
554 |
555 |
556 | 1668472640753
557 |
558 |
559 | 1668560541012
560 |
561 |
562 |
563 | 1668560541013
564 |
565 |
566 | 1668653228753
567 |
568 |
569 |
570 | 1668653228753
571 |
572 |
573 | 1668735985091
574 |
575 |
576 |
577 | 1668735985092
578 |
579 |
580 | 1668918493258
581 |
582 |
583 |
584 | 1668918493258
585 |
586 |
587 | 1668993452929
588 |
589 |
590 |
591 | 1668993452930
592 |
593 |
594 | 1669087012668
595 |
596 |
597 |
598 | 1669087012668
599 |
600 |
601 | 1669168070438
602 |
603 |
604 |
605 | 1669168070439
606 |
607 |
608 | 1669269017327
609 |
610 |
611 |
612 | 1669269017328
613 |
614 |
615 | 1669340552796
616 |
617 |
618 |
619 | 1669340552796
620 |
621 |
622 | 1669341673717
623 |
624 |
625 |
626 | 1669341673717
627 |
628 |
629 | 1669428064513
630 |
631 |
632 |
633 | 1669428064513
634 |
635 |
636 | 1669514755862
637 |
638 |
639 |
640 | 1669514755863
641 |
642 |
643 | 1669601573333
644 |
645 |
646 |
647 | 1669601573334
648 |
649 |
650 | 1669681733682
651 |
652 |
653 |
654 | 1669681733684
655 |
656 |
657 | 1669769503178
658 |
659 |
660 |
661 | 1669769503178
662 |
663 |
664 | 1669948380979
665 |
666 |
667 |
668 | 1669948380979
669 |
670 |
671 | 1670076987893
672 |
673 |
674 |
675 | 1670076987893
676 |
677 |
678 | 1670117117126
679 |
680 |
681 |
682 | 1670117117127
683 |
684 |
685 | 1670287340673
686 |
687 |
688 |
689 | 1670287340675
690 |
691 |
692 | 1670633641402
693 |
694 |
695 |
696 | 1670633641403
697 |
698 |
699 | 1670722122339
700 |
701 |
702 |
703 | 1670722122340
704 |
705 |
706 | 1671155863190
707 |
708 |
709 |
710 | 1671155863190
711 |
712 |
713 | 1671349567703
714 |
715 |
716 |
717 | 1671349567704
718 |
719 |
720 | 1671413622692
721 |
722 |
723 |
724 | 1671413622692
725 |
726 |
727 | 1671547969409
728 |
729 |
730 |
731 | 1671547969409
732 |
733 |
734 | 1671615662728
735 |
736 |
737 |
738 | 1671615662728
739 |
740 |
741 | 1672203887647
742 |
743 |
744 |
745 | 1672203887647
746 |
747 |
748 | 1672368964498
749 |
750 |
751 |
752 | 1672368964499
753 |
754 |
755 | 1672470924811
756 |
757 |
758 |
759 | 1672470924811
760 |
761 |
762 | 1672716550275
763 |
764 |
765 |
766 | 1672716550275
767 |
768 |
769 | 1672897530883
770 |
771 |
772 |
773 | 1672897530883
774 |
775 |
776 | 1673077350073
777 |
778 |
779 |
780 | 1673077350074
781 |
782 |
783 | 1673330303247
784 |
785 |
786 |
787 | 1673330303248
788 |
789 |
790 | 1673837916705
791 |
792 |
793 |
794 | 1673837916705
795 |
796 |
797 | 1674299823816
798 |
799 |
800 |
801 | 1674299823817
802 |
803 |
804 | 1674715418003
805 |
806 |
807 |
808 | 1674715418004
809 |
810 |
811 | 1675330785386
812 |
813 |
814 |
815 | 1675330785386
816 |
817 |
818 | 1675601263285
819 |
820 |
821 |
822 | 1675601263285
823 |
824 |
825 | 1676167997229
826 |
827 |
828 |
829 | 1676167997229
830 |
831 |
832 | 1676510698634
833 |
834 |
835 |
836 | 1676510698634
837 |
838 |
839 | 1676814189849
840 |
841 |
842 |
843 | 1676814189849
844 |
845 |
846 | 1677314363719
847 |
848 |
849 |
850 | 1677314363719
851 |
852 |
853 | 1678070715645
854 |
855 |
856 |
857 | 1678070715645
858 |
859 |
860 | 1678754203187
861 |
862 |
863 |
864 | 1678754203188
865 |
866 |
867 | 1680398612559
868 |
869 |
870 |
871 | 1680398612560
872 |
873 |
874 | 1681383258462
875 |
876 |
877 |
878 | 1681383258463
879 |
880 |
881 | 1683082659050
882 |
883 |
884 |
885 | 1683082659051
886 |
887 |
888 |
889 |
890 |
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
902 |
903 |
904 |
905 |
906 |
907 |
908 |
909 |
910 |
911 |
912 |
913 |
914 |
915 |
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
925 |
926 |
927 |
928 |
929 |
930 |
931 |
932 |
933 |
934 |
935 |
936 |
937 |
938 |
939 |
940 |
941 |
942 |
943 |
944 |
945 |
946 |
947 |
948 |
949 |
950 |
951 |
952 |
953 |
954 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # java学习笔记
2 |
3 | ✨ *special to meet you* ✨
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | 囊括了大部分校招所需技术栈笔记,能较好的丰富你的知识体系,增长你的能力。
13 |
14 | 刷题笔记 各个tag刷 top100 代码随想录 总有你想要的
15 | 计算机网络 Java虚拟机 操作系统等等
16 |
17 | you know "only you can stop yourself."
18 |
19 | 2022年实习秋招一定会大丰收的,坚持下去吧XDM!
20 |
21 | 
22 |
--------------------------------------------------------------------------------
/dockerNotes/docker必知必会.md:
--------------------------------------------------------------------------------
1 | # 心得体会
2 |
3 | **==并不是笔记,而是针对自己需要记忆的东西,留下痕迹。一定要学会 好好用==**
4 |
5 |
6 |
7 | - docker所解决的问题如下
8 |
9 | - docker火的原因是十分的轻巧 docker是容器化技术
10 |
11 | - docker是基于go语言开发的
12 |
13 | - [Docker Documentation | Docker Documentation](https://docs.docker.com/) docker的文档非常详细
14 | [Docker Hub](https://hub.docker.com/) docker的仓库地址
15 |
16 | - Docker如果是安在阿里云服务器上的话 还可以配置镜像加速
17 |
18 | - Docker Run的原理示意图
19 |
20 | - 启动Docker指令 systemctl start docker 运行Docker指令 docker run XXX
21 |
22 | - 底层原理
23 |
24 | - **==Docker常用的命令(其余不多记 直接看笔记)==**
25 | 
26 | 
27 |
28 | 
29 |
30 | 
31 |
32 | 
33 |
34 | 
35 |
36 | 
37 |
38 | 
39 |
40 | 
41 |
42 | 
43 |
44 | 
45 |
46 | 
47 |
48 | 
49 |
50 | 
51 |
52 | 
53 |
54 | 
55 |
56 | 
57 |
58 | 
59 |
60 |
61 |
62 | 打包后的就是类似于这样,类似虚拟机的快照
63 |
64 | 
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | 
75 |
76 |
77 |
78 | - docker images -q显示镜像id dockers images -aq 显示所有镜像id 有些隐藏的镜像也可以显示
79 |
80 | - Docker下载镜像采用的是分层下载 如果你下载一个镜像 他一些层级已经被下载过了 他就可以共用而不用下载了
81 |
82 | - markdown的使用小技巧 ```+编程语言会创建代码段
83 |
84 | - docker run -d XXX 默认是执行/bin/bash这个命令在后台启动成功后执行了就直接关闭了,如果要持久化的话 要指定一个持久的命令
85 |
86 | - touch用来新建文件 mkdir用来新建文件夹 rm用来删除文件
87 |
88 | - 当下载一个新的镜像时 可以去dockerHub上查看关注文档
89 |
90 | - Linux命令 whereis
91 | -b 只查找二进制文件。
92 |
93 | -B<目录> 只在设置的目录下查找二进制文件。
94 |
95 | -f 不显示文件名前的路径名称。
96 |
97 | -m 只查找说明文件。
98 |
99 | -M<目录> 只在设置的目录下查找说明文件。
100 |
101 | -s 只查找原始代码文件。
102 |
103 | -S<目录> 只在设置的目录下查找原始代码文件。
104 |
105 | -u 查找不包含指定类型的文件。
106 |
107 | - 用完后会自动移除 而不是还存在
108 |
109 | - 像这些镜像其实很大程度都是被阉割过的 保证最小运行就行 就比如说tomcat webapp里没东西 其实在webapp.dist中有 把它复制过来就行了
110 |
111 | - 镜像分层的理解 如果加一层是之前那层的更新 会进行替换 拉取镜像的时候 已经存在的就不会再拉了
112 |
113 | - 镜像都是只读的 当我们镜像启动容器的时候 会有个新的可写层加到镜像层的顶部,这一层我们可以进行操作 这层通常来说叫做容器层 我们所有的操作都是基于容器层的 我做的修改什么的会保存在容器层
114 |
115 | - docker -p 可以设置要映射的端口和容器端口 一个端口上只能绑定一个容器
116 |
117 | - 卷技术,就是容器目录的挂载,容器间的数据共享机制 目的就是容器的持久化和同步操作、容器间数据共享
118 |
119 | 映射过后 对容器内部的文件进行操作 会自动同步到外部 对外部进行操作 会自动同步到容器内部(就算是容器停止运行了 也会同步) **好处:我们以后修改直接在本地修改即可,容器内部会自动同步**
120 |
121 | - ==卷技术的使用 **指令**==
122 |
123 | 
124 |
125 | 
126 |
127 | 
128 |
129 | 
130 |
131 | `也可以使用dockerfile进行挂载`
132 |
133 | `容器间的挂载:--volumes-from ` 拷贝的概念
134 |
135 | 当两个挂载一到一个上面的时候 相当于全部都挂载上了 就算把挂载的那个对象删了 其他两个照样同步
136 |
137 | 
138 |
139 |
140 |
141 | - 当我拉取mysql镜像的时候,拉了mysql8版本太高 读取需要些插件 换成5.7就可以了
142 |
143 | - docker启动mysql需要做的
144 |
145 | 
146 |
147 | - 有些镜像启动需要配置环境 -e 需要去docker hub上看帮助文档进行测试
148 |
149 | - 就算在本地把对应的容器删了 但你容器中挂载出来的文件还是会存在 数据并不会丢失
150 |
151 | - 图床指的是存储图片的服务器
152 |
153 | - 如果要查看docker挂载的对应目录在哪 用docker inspect 容器id 查看具体信息 在mounts看到挂载的信息 可以找到对应的目录
154 |
155 | - 通过dockerfile 挂载卷 如果容器内没有对应的文件夹 也会自动生成 如果没有挂载卷 那么之后就要以手动的方式 -v挂载卷
156 |
157 | - ==**DockFile指令**==
158 |
159 | 
160 |
161 | 
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 | - 例子什么的 在最全笔记中看
176 |
177 | - yum -y中 -y的意思就是代替手动输入yes
178 |
179 | - $符号在Linux的shell中使用 作用就是获取一个变量的值
180 |
181 | - docker build -f 指定要使用dockerfile的路径
182 |
183 | - docker build -f zytdockfile-centos -t mycentos:0.1 ==.== 这个点的意思就是目的地址为当前地址 构建这个镜像在这个目的地址
184 |
185 | - CMD ENTRYPOINT的区别
186 | 
187 | 
188 |
189 | 在CMD命令下 如果运行时追加参数 会将CMD的命令进行替换 比如说 CMD里是 ls -a 我们在外面写个-l 会报错 除非我们些的是 ls -al 就不报错 因为会被替换
190 |
191 |
192 |
193 | - 实战Tomcat这是精髓一定要好好看,之后自己有机会发布镜像的时候 模仿这个进行构建
194 |
195 | - 构建dockerfile采用官方命名`Dockerfile`这样build的时候 都不需要指定-f了 会自动去寻找 直接
196 |
197 | ```shell
198 | docker build -t "name" #即可 会自动去寻找Dockerfile
199 | ```
200 |
201 |
202 |
203 | - WORKDIR 是进去的第一个落脚点 ENV 就是设置环境变量
204 |
205 | - 
206 | `设置PATH变量是为了让操作系统找到指定的工具程序,那么设置CLASSPATH变量的目的就是让执行环境找到程序对应的class文件以及程序中引用的其他class文件`
207 |
208 | - javaweb生成项目后默认的其实页是index.jsp和index.html
209 |
210 | - tomcat是热部署的
211 |
212 | - 自己push的镜像一定要带版本号 使用 docker tag 给镜像附上版本也可以一开始取名的时候就附上 前面一定是要自己`docker hub的用户名`/镜像名:版本号!
213 |
214 | - 除了推送到docker hub还有推送到阿里云上,阿里云推送有固定的方法
215 |
216 | - 
217 |
218 | - `Docker 网络`
219 |
220 | - 容器和容器之间是可以互相ping通的
221 |
222 | - 容器和容器之间联通实际上是通过路由器相接 删掉对应的容器 网卡就会消失
223 | 
224 |
225 | - 
226 |
227 | - 通过服务名直接ping通 不用ip地址 这样有助于当我们对应的服务器ip地址进行更换 不用重启 修改
228 |
229 | - “hosts文件是一个用于储存计算机网络中各节点信息的计算机文件;作用是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址。” 所以很多代理映射都放到这里面 `docker中--link的操作就是在hosts配置中加了一个映射` 目前已经不建议使用--link了 而是使用自定义网络 不适用docker0 因为docker0不支持服务名访问
230 |
231 | - **网络模式**
232 |
233 | - bridge : 桥接 docker(默认,自己创建也使用桥接模式)
234 | - none : 不配置网络
235 | - host : 和宿主机共享网络
236 | - container : 容器网络连同!(用的少!局限大)
237 |
238 | - 
239 | 直接启动 它会默认连接docker0 我们想用自己网络的话 可以创建一个网络 按照上面的方法启动
240 |
241 | - docker0特点:默认,域名不能访问 能通过--link打通连接 有局限性
242 | - 所以我们可以自定义网络
243 |
244 | -
245 | 
246 | 自定义网络可以直接ping 名字
247 |
248 | - **网络联通 在不同网段中的容器是无法联通的**
249 |
250 | 
251 |
252 | 联通了之后可以在对应的network inspect中看到 这就是一个容器 多个ip地址
253 |
254 | `假如要跨网络操作别人,就需要使用 docker network connect联通`
255 |
256 | - 创建集群 看狂神笔记 玩玩看
257 |
258 | - 网关是实现不同网络之间的通信 像仅仅是搭建redis集群 可以不设置网关
259 |
260 |
261 |
262 |
--------------------------------------------------------------------------------
/leetcode/Leetcode 题解刷题顺序.md:
--------------------------------------------------------------------------------
1 | # Leetcode 题解
2 |
3 | ## 前言
4 |
5 | 本文从 Leetcode 中精选大概 200 左右的题目,去除了某些繁杂但是没有多少算法思想的题目,同时保留了面试中经常被问到的经典题目。
6 |
7 | ## 算法思想
8 |
9 | - [双指针](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 双指针.md)
10 | - [排序](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 排序.md)
11 | - [贪心思想](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 贪心思想.md)
12 | - [二分查找](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 二分查找.md)
13 | - [分治](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 分治.md)
14 | - [搜索](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 搜索.md)
15 | - [动态规划](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 动态规划.md)
16 | - [数学](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 数学.md)
17 |
18 | ## 数据结构相关
19 |
20 | - [链表](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 链表.md)
21 | - [树](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 树.md)
22 | - [栈和队列](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 栈和队列.md)
23 | - [哈希表](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 哈希表.md)
24 | - [字符串](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 字符串.md)
25 | - [数组与矩阵](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 数组与矩阵.md)
26 | - [图](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 图.md)
27 | - [位运算](https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 位运算.md)
28 |
29 | ## 参考资料
30 |
31 | - Leetcode
32 | - Weiss M A, 冯舜玺. 数据结构与算法分析——C 语言描述[J]. 2004.
33 | - Sedgewick R. Algorithms[M]. Pearson Education India, 1988.
34 | - 何海涛, 软件工程师. 剑指 Offer: 名企面试官精讲典型编程题[M]. 电子工业出版社, 2014.
35 | - 《编程之美》小组. 编程之美[M]. 电子工业出版社, 2008.
36 | - 左程云. 程序员代码面试指南[M]. 电子工业出版社, 2015.
--------------------------------------------------------------------------------
/network of computer/计算机网络.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # 计算机网络 - 概述
4 | * [计算机网络 - 概述](#计算机网络---概述)
5 | * [网络的网络](#网络的网络)
6 | * [ISP](#isp)
7 | * [主机之间的通信方式](#主机之间的通信方式)
8 | * [电路交换与分组交换](#电路交换与分组交换)
9 | * [1. 电路交换](#1-电路交换)
10 | * [2. 分组交换](#2-分组交换)
11 | * [时延](#时延)
12 | * [1. 排队时延](#1-排队时延)
13 | * [2. 处理时延](#2-处理时延)
14 | * [3. 传输时延](#3-传输时延)
15 | * [4. 传播时延](#4-传播时延)
16 | * [计算机网络体系结构](#计算机网络体系结构)
17 | * [1. 五层协议](#1-五层协议)
18 | * [2. OSI](#2-osi)
19 | * [3. TCP/IP](#3-tcpip)
20 | * [4. 数据在各层之间的传递过程](#4-数据在各层之间的传递过程)
21 |
22 |
23 | ## 网络的网络
24 |
25 | 网络把主机连接起来,而互连网(internet)是把多种不同的网络连接起来,因此互连网是网络的网络。而互联网(Internet)是全球范围的互连网。
26 |
27 |
28 |
29 | ## ISP
30 |
31 | 互联网服务提供商 ISP 可以从互联网管理机构获得许多 IP 地址,同时拥有通信线路以及路由器等联网设备,个人或机构向 ISP 缴纳一定的费用就可以接入互联网。
32 |
33 |
34 |
35 | 目前的互联网是一种多层次 ISP 结构,ISP 根据覆盖面积的大小分为第一层 ISP、区域 ISP 和接入 ISP。互联网交换点 IXP 允许两个 ISP 直接相连而不用经过第三个 ISP。
36 |
37 |
38 |
39 | ## 主机之间的通信方式
40 |
41 | - 客户-服务器(C/S):客户是服务的请求方,服务器是服务的提供方。
42 |
43 |
44 |
45 | - 对等(P2P):不区分客户和服务器。
46 |
47 |
48 |
49 | ## 电路交换与分组交换
50 |
51 | ### 1. 电路交换
52 |
53 | 电路交换用于电话通信系统,两个用户要通信之前需要建立一条专用的物理链路,并且在整个通信过程中始终占用该链路。由于通信的过程中不可能一直在使用传输线路,因此电路交换对线路的利用率很低,往往不到 10%。
54 |
55 | ### 2. 分组交换
56 |
57 | 每个分组都有首部和尾部,包含了源地址和目的地址等控制信息,在同一个传输线路上同时传输多个分组互相不会影响,因此在同一条传输线路上允许同时传输多个分组,也就是说分组交换不需要占用传输线路。
58 |
59 | 在一个邮局通信系统中,邮局收到一份邮件之后,先存储下来,然后把相同目的地的邮件一起转发到下一个目的地,这个过程就是存储转发过程,分组交换也使用了存储转发过程。
60 |
61 | ## 时延
62 |
63 | 总时延 = 排队时延 + 处理时延 + 传输时延 + 传播时延
64 |
65 |
66 |
67 | ### 1. 排队时延
68 |
69 | 分组在路由器的输入队列和输出队列中排队等待的时间,取决于网络当前的通信量。
70 |
71 | ### 2. 处理时延
72 |
73 | 主机或路由器收到分组时进行处理所需要的时间,例如分析首部、从分组中提取数据、进行差错检验或查找适当的路由等。
74 |
75 | ### 3. 传输时延
76 |
77 | 主机或路由器传输数据帧所需要的时间。
78 |
79 |
80 |
81 |
82 | 其中 l 表示数据帧的长度,v 表示传输速率。
83 |
84 | ### 4. 传播时延
85 |
86 | 电磁波在信道中传播所需要花费的时间,电磁波传播的速度接近光速。
87 |
88 |
89 |
90 | 其中 l 表示信道长度,v 表示电磁波在信道上的传播速度。
91 |
92 | ## 计算机网络体系结构
93 |
94 |
95 |
96 | ### 1. 五层协议
97 |
98 | - **应用层** :为特定应用程序提供数据传输服务,例如 HTTP、DNS 等协议。数据单位为报文。
99 |
100 | - **传输层** :为进程提供通用数据传输服务。由于应用层协议很多,定义通用的传输层协议就可以支持不断增多的应用层协议。运输层包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为报文段;用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为用户数据报。TCP 主要提供完整性服务,UDP 主要提供及时性服务。
101 |
102 | - **网络层** :为主机提供数据传输服务。而传输层协议是为主机中的进程提供数据传输服务。网络层把传输层传递下来的报文段或者用户数据报封装成分组。
103 |
104 | - **数据链路层** :网络层针对的还是主机之间的数据传输服务,而主机之间可以有很多链路,链路层协议就是为同一链路的主机提供数据传输服务。数据链路层把网络层传下来的分组封装成帧。
105 |
106 | - **物理层** :考虑的是怎样在传输媒体上传输数据比特流,而不是指具体的传输媒体。物理层的作用是尽可能屏蔽传输媒体和通信手段的差异,使数据链路层感觉不到这些差异。
107 |
108 | ### 2. OSI
109 |
110 | 其中表示层和会话层用途如下:
111 |
112 | - **表示层** :数据压缩、加密以及数据描述,这使得应用程序不必关心在各台主机中数据内部格式不同的问题。
113 |
114 | - **会话层** :建立及管理会话。
115 |
116 | 五层协议没有表示层和会话层,而是将这些功能留给应用程序开发者处理。
117 |
118 | ### 3. TCP/IP
119 |
120 | 它只有四层,相当于五层协议中数据链路层和物理层合并为网络接口层。
121 |
122 | TCP/IP 体系结构不严格遵循 OSI 分层概念,应用层可能会直接使用 IP 层或者网络接口层。
123 |
124 |
125 |
126 | ### 4. 数据在各层之间的传递过程
127 |
128 | 在向下的过程中,需要添加下层协议所需要的首部或者尾部,而在向上的过程中不断拆开首部和尾部。
129 |
130 | 路由器只有下面三层协议,因为路由器位于网络核心中,不需要为进程或者应用程序提供服务,因此也就不需要传输层和应用层。
131 |
132 |
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 | * [1. 封装成帧](#1-封装成帧)
158 | * [2. 透明传输](#2-透明传输)
159 | * [3. 差错检测](#3-差错检测)
160 | * [信道分类](#信道分类)
161 | * [1. 广播信道](#1-广播信道)
162 | * [2. 点对点信道](#2-点对点信道)
163 | * [信道复用技术](#信道复用技术)
164 | * [1. 频分复用](#1-频分复用)
165 | * [2. 时分复用](#2-时分复用)
166 | * [3. 统计时分复用](#3-统计时分复用)
167 | * [4. 波分复用](#4-波分复用)
168 | * [5. 码分复用](#5-码分复用)
169 | * [CSMA/CD 协议](#csmacd-协议)
170 | * [PPP 协议](#ppp-协议)
171 | * [MAC 地址](#mac-地址)
172 | * [局域网](#局域网)
173 | * [以太网](#以太网)
174 | * [交换机](#交换机)
175 | * [虚拟局域网](#虚拟局域网)
176 |
177 | ## 基本问题
178 |
179 | (还有个滑动窗口 这里面好像是没写的)
180 |
181 | ### 1. 封装成帧
182 |
183 | 将网络层传下来的分组添加首部和尾部,用于标记帧的开始和结束。
184 |
185 |
186 |
187 | ### 2. 透明传输
188 |
189 | 透明表示一个实际存在的事物看起来好像不存在一样。
190 |
191 | 帧使用首部和尾部进行定界,如果帧的数据部分含有和首部尾部相同的内容,那么帧的开始和结束位置就会被错误的判定。需要在数据部分出现首部尾部相同的内容前面插入转义字符。如果数据部分出现转义字符,那么就在转义字符前面再加个转义字符。在接收端进行处理之后可以还原出原始数据。这个过程透明传输的内容是转义字符,用户察觉不到转义字符的存在。
192 |
193 |
194 |
195 | ### 3. 差错检测
196 |
197 | 目前数据链路层广泛使用了循环冗余检验(CRC)来检查比特差错。
198 |
199 | ## 信道分类
200 |
201 | ### 1. 广播信道
202 |
203 | 一对多通信,一个节点发送的数据能够被广播信道上所有的节点接收到。
204 |
205 | 所有的节点都在同一个广播信道上发送数据,因此需要有专门的控制方法进行协调,避免发生冲突(冲突也叫碰撞)。
206 |
207 | 主要有两种控制方法进行协调,一个是使用信道复用技术,一是使用 CSMA/CD 协议。
208 |
209 | ### 2. 点对点信道
210 |
211 | 一对一通信。
212 |
213 | 因为不会发生碰撞,因此也比较简单,使用 PPP 协议 进行控制。
214 |
215 | ## 信道复用技术
216 |
217 | ### 1. 频分复用
218 |
219 | 频分复用的所有主机在相同的时间占用不同的频率带宽资源。
220 |
221 |
222 |
223 | ### 2. 时分复用
224 |
225 | 时分复用的所有主机在不同的时间占用相同的频率带宽资源。
226 |
227 |
228 |
229 | 使用频分复用和时分复用进行通信,在通信的过程中主机会一直占用一部分信道资源。但是由于计算机数据的突发性质,通信过程没必要一直占用信道资源而不让出给其它用户使用,因此这两种方式对信道的利用率都不高。
230 |
231 | ### 3. 统计时分复用
232 |
233 | 是对时分复用的一种改进,不固定每个用户在时分复用帧中的位置,只要有数据就集中起来组成统计时分复用帧然后发送。
234 |
235 |
236 |
237 | ### 4. 波分复用
238 |
239 | 光的频分复用。由于光的频率很高,因此习惯上用波长而不是频率来表示所使用的光载波。
240 |
241 | ### 5. 码分复用
242 |
243 | 为每个用户分配 m bit 的码片,并且所有的码片正交,对于任意两个码片 和 有
244 |
245 |
246 |
247 | 为了讨论方便,取 m=8,设码片 为 00011011。在拥有该码片的用户发送比特 1 时就发送该码片,发送比特 0 时就发送该码片的反码 11100100。
248 |
249 | 在计算时将 00011011 记作 (-1 -1 -1 +1 +1 -1 +1 +1),可以得到
250 |
251 |
252 |
253 |
254 |
255 | 其中 为 的反码。
256 |
257 | 利用上面的式子我们知道,当接收端使用码片 对接收到的数据进行内积运算时,结果为 0 的是其它用户发送的数据,结果为 1 的是用户发送的比特 1,结果为 -1 的是用户发送的比特 0。
258 |
259 | 码分复用需要发送的数据量为原先的 m 倍。
260 |
261 |
262 |
263 |
264 | ## CSMA/CD 协议
265 |
266 | CSMA/CD 表示载波监听多点接入 / 碰撞检测。 (用在有线 无线的话 用的是CSMA/CA CA是碰撞避免)
267 |
268 | - **多点接入** :说明这是总线型网络,许多主机以多点的方式连接到总线上。
269 | - **载波监听** :每个主机都必须不停地监听信道。在发送前,如果监听到信道正在使用,就必须等待。
270 | - **碰撞检测** :在发送中,如果监听到信道已有其它主机正在发送数据,就表示发生了碰撞。虽然每个主机在发送数据之前都已经监听到信道为空闲,但是由于电磁波的传播时延的存在,还是有可能会发生碰撞。
271 |
272 | 记端到端的传播时延为 τ,最先发送的站点最多经过 2τ 就可以知道是否发生了碰撞,称 2τ 为 **争用期** 。只有经过争用期之后还没有检测到碰撞,才能肯定这次发送不会发生碰撞。
273 |
274 | 当发生碰撞时,站点要停止发送,等待一段时间再发送。这个时间采用 **截断二进制指数退避算法** 来确定。从离散的整数集合 {0, 1, .., (2k -1)} 中随机取出一个数,记作 r,然后取 r 倍的争用期作为重传等待时间。
275 |
276 |
277 |
278 | ## PPP 协议
279 |
280 | 互联网用户通常需要连接到某个 ISP 之后才能接入到互联网,PPP 协议是用户计算机和 ISP 进行通信时所使用的数据链路层协议。
281 |
282 |
283 |
284 | PPP 的帧格式:
285 |
286 | -
287 |
288 |
289 |
290 | ## MAC 地址
291 |
292 | MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标识网络适配器(网卡)。
293 |
294 | 一台主机拥有多少个网络适配器就有多少个 MAC 地址。例如笔记本电脑普遍存在无线网络适配器和有线网络适配器,因此就有两个 MAC 地址。
295 |
296 | ## 局域网
297 |
298 | 局域网是一种典型的广播信道,主要特点是网络为一个单位所拥有,且地理范围和站点数目均有限。
299 |
300 | 主要有以太网、令牌环网、FDDI 和 ATM 等局域网技术,目前以太网占领着有线局域网市场。
301 |
302 | 可以按照网络拓扑结构对局域网进行分类:
303 |
304 |
305 |
306 | ## 以太网
307 |
308 | 以太网是一种星型拓扑结构局域网。
309 |
310 | 早期使用集线器进行连接,集线器是一种物理层设备, 作用于比特而不是帧,当一个比特到达接口时,集线器重新生成这个比特,并将其能量强度放大,从而扩大网络的传输距离,之后再将这个比特发送到其它所有接口。如果集线器同时收到两个不同接口的帧,那么就发生了碰撞。
311 |
312 | 目前以太网使用交换机替代了集线器,交换机是一种链路层设备,它不会发生碰撞,能根据 MAC 地址进行存储转发。
313 |
314 | 以太网帧格式:
315 |
316 | - **类型** :标记上层使用的协议;
317 | - **数据** :长度在 46-1500 之间,如果太小则需要填充;
318 | - **FCS** :帧检验序列,使用的是 CRC 检验方法;
319 |
320 |
321 |
322 | ## 交换机
323 |
324 | 交换机具有自学习能力,学习的是交换表的内容,交换表中存储着 MAC 地址到接口的映射。
325 |
326 | 正是由于这种自学习能力,因此交换机是一种即插即用设备,不需要网络管理员手动配置交换表内容。
327 |
328 | 下图中,交换机有 4 个接口,主机 A 向主机 B 发送数据帧时,交换机把主机 A 到接口 1 的映射写入交换表中。为了发送数据帧到 B,先查交换表,此时没有主机 B 的表项,那么主机 A 就发送广播帧,主机 C 和主机 D 会丢弃该帧,主机 B 回应该帧向主机 A 发送数据包时,交换机查找交换表得到主机 A 映射的接口为 1,就发送数据帧到接口 1,同时交换机添加主机 B 到接口 2 的映射。
329 |
330 |
331 |
332 | ## 虚拟局域网(VLAN)
333 |
334 | 虚拟局域网可以建立与物理位置无关的逻辑组,只有在同一个虚拟局域网中的成员才会收到链路层广播信息。
335 |
336 | 例如下图中 (A1, A2, A3, A4) 属于一个虚拟局域网,A1 发送的广播会被 A2、A3、A4 收到,而其它站点收不到。
337 |
338 | 使用 VLAN 干线连接来建立虚拟局域网,每台交换机上的一个特殊接口被设置为干线接口,以互连 VLAN 交换机。IEEE 定义了一种扩展的以太网帧格式 802.1Q,它在标准以太网帧上加进了 4 字节首部 VLAN 标签,用于表示该帧属于哪一个虚拟局域网。
339 |
340 |
341 |
342 | # 计算机网络 - 网络层
343 | * [计算机网络 - 网络层](#计算机网络---网络层)
344 | * [概述](#概述)
345 | * [IP 数据报格式](#ip-数据报格式)
346 | * [IP 地址编址方式](#ip-地址编址方式)
347 | * [1. 分类](#1-分类)
348 | * [2. 子网划分](#2-子网划分)
349 | * [3. 无分类](#3-无分类)
350 | * [地址解析协议 ARP](#地址解析协议-arp)
351 | * [网际控制报文协议 ICMP](#网际控制报文协议-icmp)
352 | * [1. Ping](#1-ping)
353 | * [2. Traceroute](#2-traceroute)
354 | * [虚拟专用网 VPN](#虚拟专用网-vpn)
355 | * [网络地址转换 NAT](#网络地址转换-nat)
356 | * [路由器的结构](#路由器的结构)
357 | * [路由器分组转发流程](#路由器分组转发流程)
358 | * [路由选择协议](#路由选择协议)
359 | * [1. 内部网关协议 RIP](#1-内部网关协议-rip)
360 | * [2. 内部网关协议 OSPF](#2-内部网关协议-ospf)
361 | * [3. 外部网关协议 BGP](#3-外部网关协议-bgp)
362 |
363 |
364 | ## 概述
365 |
366 | 因为网络层是整个互联网的核心,因此应当让网络层尽可能简单。网络层向上只提供简单灵活的、无连接的、尽最大努力交互的数据报服务。
367 |
368 | 使用 IP 协议,可以把异构的物理网络连接起来,使得在网络层看起来好像是一个统一的网络。
369 |
370 |
371 |
372 | 与 IP 协议配套使用的还有三个协议:
373 |
374 | - 地址解析协议 ARP(Address Resolution Protocol)
375 | - 网际控制报文协议 ICMP(Internet Control Message Protocol)
376 | - 网际组管理协议 IGMP(Internet Group Management Protocol)
377 |
378 | ## IP 数据报格式
379 |
380 |
381 |
382 | - **版本** : 有 4(IPv4)和 6(IPv6)两个值;
383 |
384 | - **首部长度** : 占 4 位,因此最大值为 15。值为 1 表示的是 1 个 32 位字的长度,也就是 4 字节。因为固定部分长度为 20 字节,因此该值最小为 5。如果可选字段的长度不是 4 字节的整数倍,就用尾部的填充部分来填充。
385 |
386 | - **区分服务** : 用来获得更好的服务,一般情况下不使用。
387 |
388 | - **总长度** : 包括首部长度和数据部分长度。
389 |
390 | - **生存时间** :TTL,它的存在是为了防止无法交付的数据报在互联网中不断兜圈子。以路由器跳数为单位,当 TTL 为 0 时就丢弃数据报。
391 |
392 | - **协议** :指出携带的数据应该上交给哪个协议进行处理,例如 ICMP、TCP、UDP 等。
393 |
394 | - **首部检验和** :因为数据报每经过一个路由器,都要重新计算检验和,因此检验和不包含数据部分可以减少计算的工作量。
395 |
396 | - **标识** : 在数据报长度过长从而发生分片的情况下,相同数据报的不同分片具有相同的标识符。
397 |
398 | - **片偏移** : 和标识符一起,用于发生分片的情况。片偏移的单位为 8 字节。
399 |
400 |
401 |
402 | ## IP 地址编址方式
403 |
404 | IP 地址的编址方式经历了三个历史阶段:
405 |
406 | - 分类
407 | - 子网划分
408 | - 无分类
409 |
410 | ### 1. 分类
411 |
412 | 由两部分组成,网络号和主机号,其中不同分类具有不同的网络号长度,并且是固定的。
413 |
414 | IP 地址 ::= {\< 网络号 \>, \< 主机号 \>}
415 |
416 |
417 |
418 | ### 2. 子网划分
419 |
420 | 通过在主机号字段中拿一部分作为子网号,把两级 IP 地址划分为三级 IP 地址。
421 |
422 | IP 地址 ::= {\< 网络号 \>, \< 子网号 \>, \< 主机号 \>}
423 |
424 | 要使用子网,必须配置子网掩码。一个 B 类地址的默认子网掩码为 255.255.0.0,如果 B 类地址的子网占两个比特,那么子网掩码为 11111111 11111111 11000000 00000000,也就是 255.255.192.0。
425 |
426 | 注意,外部网络看不到子网的存在。
427 |
428 | ### 3. 无分类
429 |
430 | 无分类编址 CIDR 消除了传统 A 类、B 类和 C 类地址以及划分子网的概念,使用网络前缀和主机号来对 IP 地址进行编码,网络前缀的长度可以根据需要变化。
431 |
432 | IP 地址 ::= {\< 网络前缀号 \>, \< 主机号 \>}
433 |
434 | CIDR 的记法上采用在 IP 地址后面加上网络前缀长度的方法,例如 128.14.35.7/20 表示前 20 位为网络前缀。
435 |
436 | CIDR 的地址掩码可以继续称为子网掩码,子网掩码首 1 长度为网络前缀的长度。
437 |
438 | 一个 CIDR 地址块中有很多地址,一个 CIDR 表示的网络就可以表示原来的很多个网络,并且在路由表中只需要一个路由就可以代替原来的多个路由,减少了路由表项的数量。把这种通过使用网络前缀来减少路由表项的方式称为路由聚合,也称为 **构成超网** 。
439 |
440 | 在路由表中的项目由“网络前缀”和“下一跳地址”组成,在查找时可能会得到不止一个匹配结果,应当采用最长前缀匹配来确定应该匹配哪一个。
441 |
442 | ## 地址解析协议 ARP
443 |
444 | 网络层实现主机之间的通信,而链路层实现具体每段链路之间的通信。因此在通信过程中,IP 数据报的源地址和目的地址始终不变,而 MAC 地址随着链路的改变而改变。
445 |
446 |
447 |
448 | ARP 实现由 IP 地址得到 MAC 地址。
449 |
450 |
451 |
452 | 每个主机都有一个 ARP 高速缓存,里面有本局域网上的各主机和路由器的 IP 地址到 MAC 地址的映射表。
453 |
454 | 如果主机 A 知道主机 B 的 IP 地址,但是 ARP 高速缓存中没有该 IP 地址到 MAC 地址的映射,此时主机 A 通过广播的方式发送 ARP 请求分组,主机 B 收到该请求后会发送 ARP 响应分组给主机 A 告知其 MAC 地址,随后主机 A 向其高速缓存中写入主机 B 的 IP 地址到 MAC 地址的映射。
455 |
456 |
457 |
458 | ## 网际控制报文协议 ICMP
459 |
460 | ICMP 是为了更有效地转发 IP 数据报和提高交付成功的机会。它封装在 IP 数据报中,但是不属于高层协议。
461 |
462 |
463 |
464 | ICMP 报文分为差错报告报文和询问报文。
465 |
466 |
467 |
468 | ### 1. Ping
469 |
470 | Ping 是 ICMP 的一个重要应用,主要用来测试两台主机之间的连通性。
471 |
472 | Ping 的原理是通过向目的主机发送 ICMP Echo 请求报文,目的主机收到之后会发送 Echo 回答报文。Ping 会根据时间和成功响应的次数估算出数据包往返时间以及丢包率。
473 |
474 | ### 2. Traceroute
475 |
476 | Traceroute 是 ICMP 的另一个应用,用来跟踪一个分组从源点到终点的路径。
477 |
478 | Traceroute 发送的 IP 数据报封装的是无法交付的 UDP 用户数据报,并由目的主机发送终点不可达差错报告报文。
479 |
480 | - 源主机向目的主机发送一连串的 IP 数据报。第一个数据报 P1 的生存时间 TTL 设置为 1,当 P1 到达路径上的第一个路由器 R1 时,R1 收下它并把 TTL 减 1,此时 TTL 等于 0,R1 就把 P1 丢弃,并向源主机发送一个 ICMP 时间超过差错报告报文;
481 | - 源主机接着发送第二个数据报 P2,并把 TTL 设置为 2。P2 先到达 R1,R1 收下后把 TTL 减 1 再转发给 R2,R2 收下后也把 TTL 减 1,由于此时 TTL 等于 0,R2 就丢弃 P2,并向源主机发送一个 ICMP 时间超过差错报文。
482 | - 不断执行这样的步骤,直到最后一个数据报刚刚到达目的主机,主机不转发数据报,也不把 TTL 值减 1。但是因为数据报封装的是无法交付的 UDP,因此目的主机要向源主机发送 ICMP 终点不可达差错报告报文。
483 | - 之后源主机知道了到达目的主机所经过的路由器 IP 地址以及到达每个路由器的往返时间。
484 |
485 | ## 虚拟专用网 VPN
486 |
487 | 由于 IP 地址的紧缺,一个机构能申请到的 IP 地址数往往远小于本机构所拥有的主机数。并且一个机构并不需要把所有的主机接入到外部的互联网中,机构内的计算机可以使用仅在本机构有效的 IP 地址(专用地址)。
488 |
489 | 有三个专用地址块:
490 |
491 | - 10.0.0.0 \~ 10.255.255.255
492 | - 172.16.0.0 \~ 172.31.255.255
493 | - 192.168.0.0 \~ 192.168.255.255
494 |
495 | VPN 使用公用的互联网作为本机构各专用网之间的通信载体。专用指机构内的主机只与本机构内的其它主机通信;虚拟指好像是,而实际上并不是,它有经过公用的互联网。
496 |
497 | 下图中,场所 A 和 B 的通信经过互联网,如果场所 A 的主机 X 要和另一个场所 B 的主机 Y 通信,IP 数据报的源地址是 10.1.0.1,目的地址是 10.2.0.3。数据报先发送到与互联网相连的路由器 R1,R1 对内部数据进行加密,然后重新加上数据报的首部,源地址是路由器 R1 的全球地址 125.1.2.3,目的地址是路由器 R2 的全球地址 194.4.5.6。路由器 R2 收到数据报后将数据部分进行解密,恢复原来的数据报,此时目的地址为 10.2.0.3,就交付给 Y。
498 |
499 |
500 |
501 | ## 网络地址转换 NAT
502 |
503 | 专用网内部的主机使用本地 IP 地址又想和互联网上的主机通信时,可以使用 NAT 来将本地 IP 转换为全球 IP。
504 |
505 | 在以前,NAT 将本地 IP 和全球 IP 一一对应,这种方式下拥有 n 个全球 IP 地址的专用网内最多只可以同时有 n 台主机接入互联网。为了更有效地利用全球 IP 地址,现在常用的 NAT 转换表把传输层的端口号也用上了,使得多个专用网内部的主机共用一个全球 IP 地址。使用端口号的 NAT 也叫做网络地址与端口转换 NAPT。
506 |
507 |
508 |
509 | ## 路由器的结构
510 |
511 | 路由器从功能上可以划分为:路由选择和分组转发。
512 |
513 | 分组转发结构由三个部分组成:交换结构、一组输入端口和一组输出端口。
514 |
515 |
516 |
517 | ## 路由器分组转发流程
518 |
519 | - 从数据报的首部提取目的主机的 IP 地址 D,得到目的网络地址 N。
520 | - 若 N 就是与此路由器直接相连的某个网络地址,则进行直接交付;
521 | - 若路由表中有目的地址为 D 的特定主机路由,则把数据报传送给表中所指明的下一跳路由器;
522 | - 若路由表中有到达网络 N 的路由,则把数据报传送给路由表中所指明的下一跳路由器;
523 | - 若路由表中有一个默认路由,则把数据报传送给路由表中所指明的默认路由器;
524 | - 报告转发分组出错。(有些特殊的解决方法)
525 |
526 |
527 |
528 | ## 路由选择协议
529 |
530 | 路由选择协议都是自适应的,能随着网络通信量和拓扑结构的变化而自适应地进行调整。
531 |
532 | 互联网可以划分为许多较小的自治系统 AS,一个 AS 可以使用一种和别的 AS 不同的路由选择协议。
533 |
534 | 可以把路由选择协议划分为两大类:
535 |
536 | - 自治系统内部的路由选择:RIP 和 OSPF
537 | - 自治系统间的路由选择:BGP
538 |
539 | ### 1. 内部网关协议 RIP
540 |
541 | RIP 是一种基于距离向量的路由选择协议。距离是指跳数,直接相连的路由器跳数为 1。跳数最多为 15,超过 15 表示不可达。
542 |
543 | RIP 按固定的时间间隔仅和相邻路由器交换自己的路由表,经过若干次交换之后,所有路由器最终会知道到达本自治系统中任何一个网络的最短距离和下一跳路由器地址。
544 |
545 | 距离向量算法:
546 |
547 | - 对地址为 X 的相邻路由器发来的 RIP 报文,先修改报文中的所有项目,把下一跳字段中的地址改为 X,并把所有的距离字段加 1;
548 | - 对修改后的 RIP 报文中的每一个项目,进行以下步骤:
549 | - 若原来的路由表中没有目的网络 N,则把该项目添加到路由表中;
550 | - 否则:若下一跳路由器地址是 X,则把收到的项目替换原来路由表中的项目;否则:若收到的项目中的距离 d 小于路由表中的距离,则进行更新(例如原始路由表项为 Net2, 5, P,新表项为 Net2, 4, X,则更新);否则什么也不做。
551 | - 若 3 分钟还没有收到相邻路由器的更新路由表,则把该相邻路由器标为不可达,即把距离置为 16。
552 |
553 | RIP 协议实现简单,开销小。但是 RIP 能使用的最大距离为 15,限制了网络的规模。并且当网络出现故障时,要经过比较长的时间才能将此消息传送到所有路由器。
554 |
555 | ### 2. 内部网关协议 OSPF
556 |
557 | 开放最短路径优先 OSPF,是为了克服 RIP 的缺点而开发出来的。
558 |
559 | 开放表示 OSPF 不受某一家厂商控制,而是公开发表的;最短路径优先表示使用了 Dijkstra 提出的最短路径算法 SPF。
560 |
561 | OSPF 具有以下特点:
562 |
563 | - 向本自治系统中的所有路由器发送信息,这种方法是洪泛法。
564 | - 发送的信息就是与相邻路由器的链路状态,链路状态包括与哪些路由器相连以及链路的度量,度量用费用、距离、时延、带宽等来表示。
565 | - 只有当链路状态发生变化时,路由器才会发送信息。
566 |
567 | 所有路由器都具有全网的拓扑结构图,并且是一致的。相比于 RIP,OSPF 的更新过程收敛的很快。
568 |
569 | ### 3. 外部网关协议 BGP
570 |
571 | BGP(Border Gateway Protocol,边界网关协议)
572 |
573 | AS 之间的路由选择很困难,主要是由于:
574 |
575 | - 互联网规模很大;
576 | - 各个 AS 内部使用不同的路由选择协议,无法准确定义路径的度量;
577 | - AS 之间的路由选择必须考虑有关的策略,比如有些 AS 不愿意让其它 AS 经过。
578 |
579 | BGP 只能寻找一条比较好的路由,而不是最佳路由。
580 |
581 | 每个 AS 都必须配置 BGP 发言人,通过在两个相邻 BGP 发言人之间建立 TCP 连接来交换路由信息。
582 |
583 |
584 |
585 | # 计算机网络 - 传输层
586 |
587 | * [计算机网络 - 传输层](#计算机网络---传输层)
588 | * [UDP 和 TCP 的特点](#udp-和-tcp-的特点)
589 | * [UDP 首部格式](#udp-首部格式)
590 | * [TCP 首部格式](#tcp-首部格式)
591 | * [TCP 的三次握手](#tcp-的三次握手)
592 | * [TCP 的四次挥手](#tcp-的四次挥手)
593 | * [TCP 可靠传输](#tcp-可靠传输)
594 | * [TCP 滑动窗口](#tcp-滑动窗口)
595 | * [TCP 流量控制](#tcp-流量控制)
596 | * [TCP 拥塞控制](#tcp-拥塞控制)
597 | * [1. 慢开始与拥塞避免](#1-慢开始与拥塞避免)
598 | * [2. 快重传与快恢复](#2-快重传与快恢复)
599 |
600 |
601 |
602 | 网络层只把分组发送到目的主机,但是真正通信的并不是主机而是主机中的进程。传输层提供了进程间的逻辑通信,传输层向高层用户屏蔽了下面网络层的核心细节,使应用程序看起来像是在两个传输层实体之间有一条端到端的逻辑通信信道。
603 |
604 | ## UDP 和 TCP 的特点
605 |
606 | - 用户数据报协议 UDP(User Datagram Protocol)是无连接的,尽最大可能交付,没有拥塞控制,面向报文(对于应用程序传下来的报文不合并也不拆分,只是添加 UDP 首部),支持一对一、一对多、多对一和多对多的交互通信。(向上层提供无连接不可靠传输服务)
607 |
608 | - 传输控制协议 TCP(Transmission Control Protocol)是面向连接的,提供可靠交付,有流量控制,拥塞控制,提供全双工通信,面向字节流(把应用层传下来的报文看成字节流,把字节流组织成大小不等的数据块),每一条 TCP 连接只能是点对点的(一对一)。(向上层提供面向连接可靠传输服务)
609 |
610 | ## UDP 首部格式
611 |
612 |
613 |
614 | 首部字段只有 8 个字节,包括源端口、目的端口、长度、检验和。12 字节的伪首部是为了计算检验和临时添加的。
615 |
616 | ## TCP 首部格式
617 |
618 |
619 |
620 | - **序号** :用于对字节流进行编号,例如序号为 301,表示第一个字节的编号为 301,如果携带的数据长度为 100 字节,那么下一个报文段的序号应为 401。
621 |
622 | - **确认号** :期望收到的下一个报文段的序号。例如 B 正确收到 A 发送来的一个报文段,序号为 501,携带的数据长度为 200 字节,因此 B 期望下一个报文段的序号为 701,B 发送给 A 的确认报文段中确认号就为 701。
623 |
624 | - **数据偏移** :指的是数据部分距离报文段起始处的偏移量,实际上指的是首部的长度。
625 |
626 | - **确认 ACK** :当 ACK=1 时确认号字段有效,否则无效。TCP 规定,在连接建立后所有传送的报文段都必须把 ACK 置 1。
627 |
628 | - **同步 SYN** :在连接建立时用来同步序号。当 SYN=1,ACK=0 时表示这是一个连接请求报文段。若对方同意建立连接,则响应报文中 SYN=1,ACK=1。
629 |
630 | - **终止 FIN** :用来释放一个连接,当 FIN=1 时,表示此报文段的发送方的数据已发送完毕,并要求释放连接。
631 |
632 | - **窗口** :窗口值作为接收方让发送方设置其发送窗口的依据。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。
633 |
634 | ## TCP 的三次握手
635 |
636 |
637 |
638 | 假设 A 为客户端,B 为服务器端。
639 |
640 | - 首先 B 处于 LISTEN(监听)状态,等待客户的连接请求。
641 |
642 | - A 向 B 发送连接请求报文,SYN=1,ACK=0,选择一个初始的序号 x。
643 |
644 | - B 收到连接请求报文,如果同意建立连接,则向 A 发送连接确认报文,SYN=1,ACK=1,确认号为 x+1,同时也选择一个初始的序号 y。
645 |
646 | - A 收到 B 的连接确认报文后,还要向 B 发出确认,确认号为 y+1,序号为 x+1。
647 |
648 | - B 收到 A 的确认后,连接建立。
649 |
650 | **三次握手的原因**
651 |
652 | 第三次握手是为了防止失效的连接请求到达服务器,让服务器错误打开连接。
653 |
654 | 客户端发送的连接请求如果在网络中滞留,那么就会隔很长一段时间才能收到服务器端发回的连接确认。客户端等待一个超时重传时间之后,就会重新请求连接。但是这个滞留的连接请求最后还是会到达服务器,如果不进行三次握手,那么服务器就会打开两个连接。如果有第三次握手,客户端会忽略服务器之后发送的对滞留连接请求的连接确认,不进行第三次握手,因此就不会再次打开连接。
655 |
656 | ## TCP 的四次挥手
657 |
658 |
659 |
660 | 以下描述不讨论序号和确认号,因为序号和确认号的规则比较简单。并且不讨论 ACK,因为 ACK 在连接建立之后都为 1。
661 |
662 | - A 发送连接释放报文,FIN=1。
663 |
664 | - B 收到之后发出确认,此时 TCP 属于半关闭状态,B 能向 A 发送数据但是 A 不能向 B 发送数据。
665 |
666 | - 当 B 不再需要连接时,发送连接释放报文,FIN=1。
667 |
668 | - A 收到后发出确认,进入 TIME-WAIT 状态,等待 2 MSL(最大报文存活时间)后释放连接。
669 |
670 | - B 收到 A 的确认后释放连接。
671 |
672 | **四次挥手的原因**
673 |
674 | 客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器会发送 FIN 连接释放报文。
675 |
676 | **TIME_WAIT**
677 |
678 | 客户端接收到服务器端的 FIN 报文后进入此状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:
679 |
680 | - 确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。
681 |
682 | - 等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文。
683 |
684 | ## TCP 可靠传输
685 |
686 | TCP 使用超时重传来实现可靠传输:如果一个已经发送的报文段在超时时间内没有收到确认,那么就重传这个报文段。
687 |
688 | 一个报文段从发送再到接收到确认所经过的时间称为往返时间 RTT,加权平均往返时间 RTTs 计算如下:
689 |
690 |
691 | 其中,0 ≤ a < 1,RTTs 随着 a 的增加更容易受到 RTT 的影响。
692 |
693 | 超时时间 RTO 应该略大于 RTTs,TCP 使用的超时时间计算如下:
694 |
695 |
696 | 其中 RTTd 为偏差的加权平均值。
697 |
698 | ## TCP 滑动窗口
699 |
700 | 窗口是缓存的一部分,用来暂时存放字节流。发送方和接收方各有一个窗口,接收方通过 TCP 报文段中的窗口字段告诉发送方自己的窗口大小,发送方根据这个值和其它信息设置自己的窗口大小。
701 |
702 | 发送窗口内的字节都允许被发送,接收窗口内的字节都允许被接收。如果发送窗口左部的字节已经发送并且收到了确认,那么就将发送窗口向右滑动一定距离,直到左部第一个字节不是已发送并且已确认的状态;接收窗口的滑动类似,接收窗口左部字节已经发送确认并交付主机,就向右滑动接收窗口。
703 |
704 | 接收窗口只会对窗口内最后一个按序到达的字节进行确认,例如接收窗口已经收到的字节为 {31, 34, 35},其中 {31} 按序到达,而 {34, 35} 就不是,因此只对字节 31 进行确认。发送方得到一个字节的确认之后,就知道这个字节之前的所有字节都已经被接收。
705 |
706 |
707 |
708 | ## TCP 流量控制
709 |
710 | 流量控制是为了控制发送方发送速率,保证接收方来得及接收。
711 |
712 | 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据。
713 |
714 | ## TCP 拥塞控制
715 |
716 | 如果网络出现拥塞,分组将会丢失,此时发送方会继续重传,从而导致网络拥塞程度更高。因此当出现拥塞时,应当控制发送方的速率。这一点和流量控制很像,但是出发点不同。流量控制是为了让接收方能来得及接收,而拥塞控制是为了降低整个网络的拥塞程度。
717 |
718 |
719 |
720 | TCP 主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。
721 |
722 | 发送方需要维护一个叫做拥塞窗口(cwnd)的状态变量,注意拥塞窗口与发送方窗口的区别:拥塞窗口只是一个状态变量,实际决定发送方能发送多少数据的是发送方窗口。
723 |
724 | 为了便于讨论,做如下假设:
725 |
726 | - 接收方有足够大的接收缓存,因此不会发生流量控制;
727 | - 虽然 TCP 的窗口基于字节,但是这里设窗口的大小单位为报文段。
728 |
729 |
730 |
731 | ### 1. 慢开始与拥塞避免
732 |
733 | 发送的最初执行慢开始,令 cwnd = 1,发送方只能发送 1 个报文段;当收到确认后,将 cwnd 加倍,因此之后发送方能够发送的报文段数量为:2、4、8 ...
734 |
735 | 注意到慢开始每个轮次都将 cwnd 加倍,这样会让 cwnd 增长速度非常快,从而使得发送方发送的速度增长速度过快,网络拥塞的可能性也就更高。设置一个慢开始门限 ssthresh,当 cwnd \>= ssthresh 时,进入拥塞避免,每个轮次只将 cwnd 加 1。
736 |
737 | 如果出现了超时,则令 ssthresh = cwnd / 2,然后重新执行慢开始。
738 |
739 | ### 2. 快重传与快恢复
740 |
741 | 在接收方,要求每次接收到报文段都应该对最后一个已收到的有序报文段进行确认。例如已经接收到 M1 和 M2 ,此时收到 M4 ,应当发送对 M2 的确认。
742 |
743 | 在发送方,如果收到三个重复确认,那么可以知道下一个报文段丢失,此时执行快重传,立即重传下一个报文段。例如收到三个 M2 ,则 M3 丢失,立即重传 M3 。
744 |
745 | 在这种情况下,只是丢失个别报文段,而不是网络拥塞。因此执行快恢复,令 ssthresh = cwnd / 2 ,cwnd = ssthresh,注意到此时直接进入拥塞避免。
746 |
747 | 慢开始和快恢复的快慢指的是 cwnd 的设定值,而不是 cwnd 的增长速率。慢开始 cwnd 设定为 1,而快恢复 cwnd 设定为 ssthresh。
748 |
749 |
750 |
751 | # 计算机网络 - 应用层
752 |
753 | * [计算机网络 - 应用层](#计算机网络---应用层)
754 | * [域名系统](#域名系统)
755 | * [文件传送协议](#文件传送协议)
756 | * [动态主机配置协议](#动态主机配置协议)
757 | * [远程登录协议](#远程登录协议)
758 | * [电子邮件协议](#电子邮件协议)
759 | * [1. SMTP](#1-smtp)
760 | * [2. POP3](#2-pop3)
761 | * [3. IMAP](#3-imap)
762 | * [常用端口](#常用端口)
763 | * [Web 页面请求过程](#web-页面请求过程)
764 | * [1. DHCP 配置主机信息](#1-dhcp-配置主机信息)
765 | * [2. ARP 解析 MAC 地址](#2-arp-解析-mac-地址)
766 | * [3. DNS 解析域名](#3-dns-解析域名)
767 | * [4. HTTP 请求页面](#4-http-请求页面)
768 |
769 |
770 |
771 | ## 域名系统
772 |
773 | DNS 是一个分布式数据库,提供了主机名和 IP 地址之间相互转换的服务。这里的分布式数据库是指,每个站点只保留它自己的那部分数据。
774 |
775 | 域名具有层次结构,从上到下依次为:根域名、顶级域名、二级域名。
776 |
777 |
778 |
779 | DNS 可以使用 UDP 或者 TCP 进行传输,使用的端口号都为 53。大多数情况下 DNS 使用 UDP 进行传输,这就要求域名解析器和域名服务器都必须自己处理超时和重传从而保证可靠性。在两种情况下会使用 TCP 进行传输:
780 |
781 | - 如果返回的响应超过的 512 字节(UDP 最大只支持 512 字节的数据)。
782 | - 区域传送(区域传送是主域名服务器向辅助域名服务器传送变化的那部分数据)。
783 |
784 | ## 文件传送协议
785 |
786 | FTP 使用 TCP 进行连接,它需要两个连接来传送一个文件:
787 |
788 | - 控制连接:服务器打开端口号 21 等待客户端的连接,客户端主动建立连接后,使用这个连接将客户端的命令传送给服务器,并传回服务器的应答。
789 | - 数据连接:用来传送一个文件数据。
790 |
791 | 根据数据连接是否是服务器端主动建立,FTP 有主动和被动两种模式:
792 |
793 | - 主动模式:服务器端主动建立数据连接,其中服务器端的端口号为 20,客户端的端口号随机,但是必须大于 1024,因为 0\~1023 是熟知端口号。
794 |
795 |
796 |
797 | - 被动模式:客户端主动建立数据连接,其中客户端的端口号由客户端自己指定,服务器端的端口号随机。
798 |
799 |
800 |
801 | 主动模式要求客户端开放端口号给服务器端,需要去配置客户端的防火墙。被动模式只需要服务器端开放端口号即可,无需客户端配置防火墙。但是被动模式会导致服务器端的安全性减弱,因为开放了过多的端口号。
802 |
803 | ## 动态主机配置协议
804 |
805 | DHCP (Dynamic Host Configuration Protocol) 提供了即插即用的连网方式,用户不再需要手动配置 IP 地址等信息。
806 |
807 | DHCP 配置的内容不仅是 IP 地址,还包括子网掩码、网关 IP 地址。
808 |
809 | DHCP 工作过程如下:
810 |
811 | 1. 客户端发送 Discover 报文,该报文的目的地址为 255.255.255.255:67,源地址为 0.0.0.0:68,被放入 UDP 中,该报文被广播到同一个子网的所有主机上。如果客户端和 DHCP 服务器不在同一个子网,就需要使用中继代理。
812 | 2. DHCP 服务器收到 Discover 报文之后,发送 Offer 报文给客户端,该报文包含了客户端所需要的信息。因为客户端可能收到多个 DHCP 服务器提供的信息,因此客户端需要进行选择。
813 | 3. 如果客户端选择了某个 DHCP 服务器提供的信息,那么就发送 Request 报文给该 DHCP 服务器。
814 | 4. DHCP 服务器发送 Ack 报文,表示客户端此时可以使用提供给它的信息。
815 |
816 |
817 |
818 | ## 远程登录协议
819 |
820 | TELNET 用于登录到远程主机上,并且远程主机上的输出也会返回。
821 |
822 | TELNET 可以适应许多计算机和操作系统的差异,例如不同操作系统系统的换行符定义。
823 |
824 | ## 电子邮件协议
825 |
826 | 一个电子邮件系统由三部分组成:用户代理、邮件服务器以及邮件协议。
827 |
828 | 邮件协议包含发送协议和读取协议,发送协议常用 SMTP,读取协议常用 POP3 和 IMAP。
829 |
830 |
831 |
832 | ### 1. SMTP
833 |
834 | SMTP 只能发送 ASCII 码,而互联网邮件扩充 MIME 可以发送二进制文件。MIME 并没有改动或者取代 SMTP,而是增加邮件主体的结构,定义了非 ASCII 码的编码规则。
835 |
836 |
837 |
838 | ### 2. POP3
839 |
840 | POP3 的特点是只要用户从服务器上读取了邮件,就把该邮件删除。但最新版本的 POP3 可以不删除邮件。
841 |
842 | ### 3. IMAP
843 |
844 | IMAP 协议中客户端和服务器上的邮件保持同步,如果不手动删除邮件,那么服务器上的邮件也不会被删除。IMAP 这种做法可以让用户随时随地去访问服务器上的邮件。
845 |
846 | ## 常用端口
847 |
848 | | 应用 | 应用层协议 | 端口号 | 传输层协议 | 备注 |
849 | | :--------------: | :--------: | :-----: | :--------: | :-------------------------: |
850 | | 域名解析 | DNS | 53 | UDP/TCP | 长度超过 512 字节时使用 TCP |
851 | | 动态主机配置协议 | DHCP | 67/68 | UDP | |
852 | | 简单网络管理协议 | SNMP | 161/162 | UDP | |
853 | | 文件传送协议 | FTP | 20/21 | TCP | 控制连接 21,数据连接 20 |
854 | | 远程终端协议 | TELNET | 23 | TCP | |
855 | | 超文本传送协议 | HTTP | 80 | TCP | |
856 | | 简单邮件传送协议 | SMTP | 25 | TCP | |
857 | | 邮件读取协议 | POP3 | 110 | TCP | |
858 | | 网际报文存取协议 | IMAP | 143 | TCP | |
859 |
860 | ## Web 页面请求过程
861 |
862 | ### 1. DHCP 配置主机信息
863 |
864 | - 假设主机最开始没有 IP 地址以及其它信息,那么就需要先使用 DHCP 来获取。
865 |
866 | - 主机生成一个 DHCP 请求报文,并将这个报文放入具有目的端口 67 和源端口 68 的 UDP 报文段中。
867 |
868 | - 该报文段则被放入在一个具有广播 IP 目的地址(255.255.255.255) 和源 IP 地址(0.0.0.0)的 IP 数据报中。
869 |
870 | - 该数据报则被放置在 MAC 帧中,该帧具有目的地址 FF:\FF:\FF:\FF:\FF:FF,将广播到与交换机连接的所有设备。
871 |
872 | - 连接在交换机的 DHCP 服务器收到广播帧之后,不断地向上分解得到 IP 数据报、UDP 报文段、DHCP 请求报文,之后生成 DHCP ACK 报文,该报文包含以下信息:IP 地址、DNS 服务器的 IP 地址、默认网关路由器的 IP 地址和子网掩码。该报文被放入 UDP 报文段中,UDP 报文段有被放入 IP 数据报中,最后放入 MAC 帧中。
873 |
874 | - 该帧的目的地址是请求主机的 MAC 地址,因为交换机具有自学习能力,之前主机发送了广播帧之后就记录了 MAC 地址到其转发接口的交换表项,因此现在交换机就可以直接知道应该向哪个接口发送该帧。
875 |
876 | - 主机收到该帧后,不断分解得到 DHCP 报文。之后就配置它的 IP 地址、子网掩码和 DNS 服务器的 IP 地址,并在其 IP 转发表中安装默认网关。
877 |
878 | ### 2. ARP 解析 MAC 地址
879 |
880 | - 主机通过浏览器生成一个 TCP 套接字,套接字向 HTTP 服务器发送 HTTP 请求。为了生成该套接字,主机需要知道网站的域名对应的 IP 地址。
881 |
882 | - 主机生成一个 DNS 查询报文,该报文具有 53 号端口,因为 DNS 服务器的端口号是 53。
883 |
884 | - 该 DNS 查询报文被放入目的地址为 DNS 服务器 IP 地址的 IP 数据报中。
885 |
886 | - 该 IP 数据报被放入一个以太网帧中,该帧将发送到网关路由器。
887 |
888 | - DHCP 过程只知道网关路由器的 IP 地址,为了获取网关路由器的 MAC 地址,需要使用 ARP 协议。
889 |
890 | - 主机生成一个包含目的地址为网关路由器 IP 地址的 ARP 查询报文,将该 ARP 查询报文放入一个具有广播目的地址(FF:\FF:\FF:\FF:\FF:FF)的以太网帧中,并向交换机发送该以太网帧,交换机将该帧转发给所有的连接设备,包括网关路由器。
891 |
892 | - 网关路由器接收到该帧后,不断向上分解得到 ARP 报文,发现其中的 IP 地址与其接口的 IP 地址匹配,因此就发送一个 ARP 回答报文,包含了它的 MAC 地址,发回给主机。
893 |
894 | ### 3. DNS 解析域名
895 |
896 | - 知道了网关路由器的 MAC 地址之后,就可以继续 DNS 的解析过程了。
897 |
898 | - 网关路由器接收到包含 DNS 查询报文的以太网帧后,抽取出 IP 数据报,并根据转发表决定该 IP 数据报应该转发的路由器。
899 |
900 | - 因为路由器具有内部网关协议(RIP、OSPF)和外部网关协议(BGP)这两种路由选择协议,因此路由表中已经配置了网关路由器到达 DNS 服务器的路由表项。
901 |
902 | - 到达 DNS 服务器之后,DNS 服务器抽取出 DNS 查询报文,并在 DNS 数据库中查找待解析的域名。
903 |
904 | - 找到 DNS 记录之后,发送 DNS 回答报文,将该回答报文放入 UDP 报文段中,然后放入 IP 数据报中,通过路由器反向转发回网关路由器,并经过以太网交换机到达主机。
905 |
906 | ### 4. HTTP 请求页面
907 |
908 | - 有了 HTTP 服务器的 IP 地址之后,主机就能够生成 TCP 套接字,该套接字将用于向 Web 服务器发送 HTTP GET 报文。
909 |
910 | - 在生成 TCP 套接字之前,必须先与 HTTP 服务器进行三次握手来建立连接。生成一个具有目的端口 80 的 TCP SYN 报文段,并向 HTTP 服务器发送该报文段。
911 |
912 | - HTTP 服务器收到该报文段之后,生成 TCP SYN ACK 报文段,发回给主机。
913 |
914 | - 连接建立之后,浏览器生成 HTTP GET 报文,并交付给 HTTP 服务器。
915 |
916 | - HTTP 服务器从 TCP 套接字读取 HTTP GET 报文,生成一个 HTTP 响应报文,将 Web 页面内容放入报文主体中,发回给主机。
917 |
918 | - 浏览器收到 HTTP 响应报文后,抽取出 Web 页面内容,之后进行渲染,显示 Web 页面。
--------------------------------------------------------------------------------
/open source project learning method/开源项目学习.md:
--------------------------------------------------------------------------------
1 | # 开源项目学习
2 |
3 |
4 |
5 |
6 |
7 | ## 学习步骤(对所有开源项目来说)
8 |
9 |
10 |
11 | ### 开源项目下载
12 |
13 | 下载完毕,然后解压,优先使用码云下载!
14 |
15 | 解压,先不要着急运行!
16 |
17 | **观察:**
18 |
19 | 1、用了那些技术
20 |
21 | 2、是否有数据库
22 |
23 | 3、你的环境是否匹配
24 |
25 | 通过了,然后再想办法运行!
26 |
27 |
28 |
29 | ### 跑起来是第一步
30 |
31 | 1、安装数据库,执行SQL(如果它没有建库语句 则自己进行建库)
32 |
33 | 2、前端需要跑起来 前端依赖下载等...
34 |
35 | 3、后端项目==导入==跑起来 (idea直接import Project open的话会很麻烦的)
36 |
37 | 4、**启动后端项目(一般前后端项目 前端是依赖后端的)** 启动的先后顺序 先分析模块 主要分析common、system等模块 如果发现有redis等 需要先启动redis, 进而还要看看它的配置文件,看看端口号是否和自己是一致,再看看有那些配置需要改成自己的配置,比如数据库账号密码等
38 |
39 | tip:只要发现了Swagger,那么跑起来的第一步就是先进入Swagger-ui页面!因为这里面都是接口!
40 |
41 |
42 |
43 | ### 前后端分离项目固定套路
44 |
45 | 1、从前端开始分析。打开控制台,点一个接口,分析一波调用关系!
46 |
47 | 2、前后端端口调用不一致~8013 -- 8000
48 |
49 | - 封装了接口请求 ajax axios request
50 |
51 | - 找到配置
52 |
53 | 
54 |
55 | - 前后端分离项目的重点:找到接口的调用关系
56 | - Springboot提供服务!前端调用接口数据!Vue负责渲染页面!
57 |
58 | 
59 |
60 | - 前端项目固定套路
61 |
62 | 
63 |
64 | - 在api中每个方法 后端都一定有接口 复制一下路径到idea中用CTRL+SHIFT+F 来看
65 | - 通过抓取前端的请求,找到后端对应接口
66 |
67 | 
68 |
69 | - 去后端进行全局搜索 找到后端对应的地址 接下来就可以进行深挖了
70 |
71 | 
72 |
73 | - Controller--Service--Dao:接下来就能看懂了
74 | - 现在从前到后可以分析了!但是如何渲染到视图上呢?看前端
75 |
76 | 
77 |
78 | - vue标准套路
79 |
80 | ```vue
81 |
82 | 视图层
83 |
84 |
85 |
92 |
93 |
96 | ```
97 |
98 |
99 |
100 | - 如果你现在自己的项目或者你要学习一个模块,将这个模块独立抽取出来即可!删除法
101 |
102 |
103 |
104 | ### 如何找到一个好的开源项目
105 |
106 |
107 |
108 | 1、找分类 JAVA
109 |
110 | 2、看收藏,开源项目,所有人觉得不错,那就是好的!
111 |
112 | 3、看具有价值
113 |
114 | 4、根据自身的理解情况去看
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/operation system/操作系统.md:
--------------------------------------------------------------------------------
1 | # 操作系统
2 |
3 | # 计算机操作系统 - 概述
4 |
5 | * [计算机操作系统 - 概述](#计算机操作系统---概述)
6 | * [基本特征](#基本特征)
7 | * [1. 并发](#1-并发)
8 | * [2. 共享](#2-共享)
9 | * [3. 虚拟](#3-虚拟)
10 | * [4. 异步](#4-异步)
11 | * [基本功能](#基本功能)
12 | * [1. 进程管理](#1-进程管理)
13 | * [2. 内存管理](#2-内存管理)
14 | * [3. 文件管理](#3-文件管理)
15 | * [4. 设备管理](#4-设备管理)
16 | * [系统调用](#系统调用)
17 | * [宏内核和微内核](#宏内核和微内核)
18 | * [1. 宏内核](#1-宏内核)
19 | * [2. 微内核](#2-微内核)
20 | * [中断分类](#中断分类)
21 | * [1. 外中断](#1-外中断)
22 | * [2. 异常](#2-异常)
23 | * [3. 陷入](#3-陷入)
24 |
25 |
26 |
27 | ## 基本特征
28 |
29 | ### 1. 并发
30 |
31 | 并发是指宏观上在一段时间内能同时运行多个程序,而并行则指同一时刻能运行多个指令。
32 |
33 | 并行需要硬件支持,如多流水线、多核处理器或者分布式计算系统。
34 |
35 | 操作系统通过引入进程和线程,使得程序能够并发运行。
36 |
37 | ### 2. 共享
38 |
39 | 共享是指系统中的资源可以被多个并发进程共同使用。
40 |
41 | 有两种共享方式:互斥共享和同时共享。
42 |
43 | 互斥共享的资源称为临界资源,例如打印机等,在同一时刻只允许一个进程访问,需要用同步机制来实现互斥访问。
44 |
45 | ### 3. 虚拟
46 |
47 | 虚拟技术把一个物理实体转换为多个逻辑实体。
48 |
49 | 主要有两种虚拟技术:时(时间)分复用技术和空(空间)分复用技术。
50 |
51 | 多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占用处理器,每次只执行一小个时间片并快速切换。
52 |
53 | 虚拟内存使用了空分复用技术,它将物理内存抽象为地址空间,每个进程都有各自的地址空间。地址空间的页被映射到物理内存,地址空间的页并不需要全部在物理内存中,当使用到一个没有在物理内存的页时,执行页面置换算法,将该页置换到内存中。
54 |
55 | ### 4. 异步
56 |
57 | 异步指进程不是一次性执行完毕,而是走走停停,以不可知的速度向前推进。
58 |
59 | ## 基本功能
60 |
61 | ### 1. 进程管理
62 |
63 | 进程控制、进程同步、进程通信、死锁处理、处理机调度等。
64 |
65 | ### 2. 内存管理
66 |
67 | 内存分配、地址映射、内存保护与共享、虚拟内存等。
68 |
69 | ### 3. 文件管理
70 |
71 | 文件存储空间的管理、目录管理、文件读写管理和保护等。
72 |
73 | ### 4. 设备管理
74 |
75 | 完成用户的 I/O 请求,方便用户使用各种设备,并提高设备的利用率。
76 |
77 | 主要包括缓冲管理、设备分配、设备处理、虛拟设备等。
78 |
79 | ## 系统调用
80 |
81 | 如果一个进程在用户态需要使用内核态的功能,就进行系统调用从而陷入内核,由操作系统代为完成。
82 |
83 |
84 |
85 | Linux 的系统调用主要有以下这些:
86 |
87 | | Task | Commands |
88 | | :------: | --------------------------- |
89 | | 进程控制 | fork(); exit(); wait(); |
90 | | 进程通信 | pipe(); shmget(); mmap(); |
91 | | 文件操作 | open(); read(); write(); |
92 | | 设备操作 | ioctl(); read(); write(); |
93 | | 信息维护 | getpid(); alarm(); sleep(); |
94 | | 安全 | chmod(); umask(); chown(); |
95 |
96 | ## 宏内核和微内核
97 |
98 | ### 1. 宏内核
99 |
100 | 宏内核是将操作系统功能作为一个紧密结合的整体放到内核。
101 |
102 | 由于各模块共享信息,因此有很高的性能。
103 |
104 | ### 2. 微内核
105 |
106 | 由于操作系统不断复杂,因此将一部分操作系统功能移出内核,从而降低内核的复杂性。移出的部分根据分层的原则划分成若干服务,相互独立。
107 |
108 | 在微内核结构下,操作系统被划分成小的、定义良好的模块,只有微内核这一个模块运行在内核态,其余模块运行在用户态。
109 |
110 | 因为需要频繁地在用户态和核心态之间进行切换,所以会有一定的性能损失。
111 |
112 |
113 |
114 | ## 中断分类
115 |
116 | ### 1. 外中断
117 |
118 | 由 CPU 执行指令以外的事件引起,如 I/O 完成中断,表示设备输入/输出处理已经完成,处理器能够发送下一个输入/输出请求。此外还有时钟中断、控制台中断等。
119 |
120 | (下面2、3属于内中断 内外中断的区别就是来源于cpu的内部还是外部)
121 |
122 | ### 2. 异常
123 |
124 | 由 CPU 执行指令的内部事件引起,如非法操作码、地址越界、算术溢出等。
125 |
126 | ### 3. 陷入
127 |
128 | 在用户程序中使用系统调用。
129 |
130 | # 计算机操作系统 - 进程管理
131 |
132 | * [计算机操作系统 - 进程管理](#计算机操作系统---进程管理)
133 | * [进程与线程](#进程与线程)
134 | * [1. 进程](#1-进程)
135 | * [2. 线程](#2-线程)
136 | * [3. 区别](#3-区别)
137 | * [进程状态的切换](#进程状态的切换)
138 | * [进程调度算法](#进程调度算法)
139 | * [1. 批处理系统](#1-批处理系统)
140 | * [2. 交互式系统](#2-交互式系统)
141 | * [3. 实时系统](#3-实时系统)
142 | * [进程同步](#进程同步)
143 | * [1. 临界区](#1-临界区)
144 | * [2. 同步与互斥](#2-同步与互斥)
145 | * [3. 信号量](#3-信号量)
146 | * [4. 管程](#4-管程)
147 | * [经典同步问题](#经典同步问题)
148 | * [1. 哲学家进餐问题](#1-哲学家进餐问题)
149 | * [2. 读者-写者问题](#2-读者-写者问题)
150 | * [进程通信](#进程通信)
151 | * [1. 管道](#1-管道)
152 | * [2. FIFO](#2-fifo)
153 | * [3. 消息队列](#3-消息队列)
154 | * [4. 信号量](#4-信号量)
155 | * [5. 共享存储](#5-共享存储)
156 | * [6. 套接字](#6-套接字)
157 |
158 |
159 |
160 | ## 进程与线程
161 |
162 | ### 1. 进程
163 |
164 | (进程控制是用原语实现的,原语的执行 必须一气呵成,不可中断)
165 |
166 | 进程是资源分配的基本单位。
167 |
168 | 进程控制块 (Process Control Block, PCB) 描述进程的基本信息和运行状态,所谓的创建进程和撤销进程,都是指对 PCB 的操作。(pcb是进程存在的唯一标志!)
169 |
170 | 下图显示了 4 个程序创建了 4 个进程,这 4 个进程可以并发地执行。
171 |
172 |
173 |
174 | ### 2. 线程
175 |
176 | 线程是独立调度的基本单位。
177 |
178 | (分为用户级线程 是从用户视角下能看到的线程 内核级线程 是从操作系统内核视角看能看到的线程)
179 |
180 | 一个进程中可以有多个线程,它们共享进程资源。
181 |
182 | QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 HTTP 请求线程、事件响应线程、渲染线程等等,线程的并发执行使得在浏览器中点击一个新链接从而发起 HTTP 请求时,浏览器还可以响应用户的其它事件。
183 |
184 |
185 |
186 | ### 3. 区别
187 |
188 | Ⅰ 拥有资源
189 |
190 | 进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。
191 |
192 | Ⅱ 调度
193 |
194 | 线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
195 |
196 | Ⅲ 系统开销
197 |
198 | 由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,所付出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小。
199 |
200 | Ⅳ 通信方面
201 |
202 | 线程间可以通过直接读写同一进程中的数据进行通信,但是进程通信需要借助 IPC。
203 |
204 | ## 进程状态的切换
205 |
206 |
207 |
208 | - 就绪状态(ready):等待被调度
209 | - 运行状态(running)
210 | - 阻塞状态(waiting):等待资源
211 |
212 | 应该注意以下内容:
213 |
214 | - 只有就绪态和运行态可以相互转换,其它的都是单向转换。就绪状态的进程通过调度算法从而获得 CPU 时间,转为运行状态;而运行状态的进程,在分配给它的 CPU 时间片用完之后就会转为就绪状态,等待下一次调度。
215 | - 阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU 时间,缺少 CPU 时间会从运行态转换为就绪态。
216 |
217 | ## 进程调度算法
218 |
219 | 不同环境的调度算法目标不同,因此需要针对不同环境来讨论调度算法。
220 |
221 | ### 1. 批处理系统
222 |
223 | 批处理系统没有太多的用户操作,在该系统中,调度算法目标是保证吞吐量和周转时间(从提交到终止的时间)。
224 |
225 |
226 |
227 | #### 三种层次的调度
228 |
229 | - 作业调度(高级调度):从外存的后备队列中选择一批作业进入内存,并为它们创建进程
230 | - 内存调度(中级调度):使那些暂时不能运行的进程调至外存等待,把外存上已经具备运行条件的就绪进程重新调入内存
231 | - 进程调度(低级调度):从就绪队列中选取一个进程,将处理机分配给它。发生的频率最高
232 |
233 |
234 |
235 | **1.1 先来先服务 first-come first-serverd(FCFS)** (非抢占式)
236 |
237 | 非抢占式的调度算法,按照请求的顺序进行调度。
238 |
239 | 有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。
240 |
241 | **1.2 短作业优先 shortest job first(SJF)**(非抢占式)
242 |
243 | 非抢占式的调度算法,按估计运行时间最短的顺序进行调度。
244 |
245 | 长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。
246 |
247 | **1.3 最短剩余时间优先 shortest remaining time next(SRTN)** (抢占式)
248 |
249 | 最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。 当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。
250 |
251 |
252 |
253 | (有个高响应比优先 是综合了fcfs sjf 两者的优点)
254 |
255 |
256 |
257 |
258 |
259 | ### 2. 交互式系统
260 |
261 | 交互式系统有大量的用户交互操作,在该系统中调度算法的目标是快速地进行响应。
262 |
263 | **2.1 时间片轮转**
264 |
265 | 将所有就绪进程按 FCFS 的原则排成一个队列,每次调度时,把 CPU 时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把 CPU 时间分配给队首的进程。
266 |
267 | 时间片轮转算法的效率和时间片的大小有很大关系:
268 |
269 | - 因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间。
270 | - 而如果时间片过长,那么实时性就不能得到保证。
271 |
272 |
273 |
274 | **2.2 优先级调度**
275 |
276 | 为每个进程分配一个优先级,按优先级进行调度。
277 |
278 | 为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。
279 |
280 | **2.3 多级反馈队列**
281 |
282 | 一个进程需要执行 100 个时间片,如果采用时间片轮转调度算法,那么需要交换 100 次。
283 |
284 | 多级队列是为这种需要连续执行多个时间片的进程考虑,它设置了多个队列,每个队列时间片大小都不同,例如 1,2,4,8,..。进程在第一个队列没执行完,就会被移到下一个队列。这种方式下,之前的进程只需要交换 7 次。
285 |
286 | 每个队列优先权也不同,最上面的优先权最高。因此只有上一个队列没有进程在排队,才能调度当前队列上的进程。
287 |
288 | 可以将这种调度算法看成是时间片轮转调度算法和优先级调度算法的结合。
289 |
290 |
291 |
292 | ### 3. 实时系统
293 |
294 | 实时系统要求一个请求在一个确定时间内得到响应。
295 |
296 | 分为硬实时和软实时,前者必须满足绝对的截止时间,后者可以容忍一定的超时。
297 |
298 | ## 进程同步
299 |
300 | ### 1. 临界区
301 |
302 | (临界资源是一次仅允许一个进程使用的共享资源。各进程采取互斥的方式,实现共享的资源称作临界资源。 )
303 |
304 | 对临界资源进行访问的那段代码称为临界区。
305 |
306 | 为了互斥访问临界资源,每个进程在进入临界区之前,需要先进行检查。
307 |
308 | ```html
309 | // entry section
310 | // critical section;
311 | // exit section
312 | ```
313 |
314 | ### 2. 同步与互斥
315 |
316 | - 同步:多个进程因为合作产生的直接制约关系,使得进程有一定的先后执行关系。
317 | - 互斥:多个进程在同一时刻只有一个进程能进入临界区。(另一个进程必须等待) (进程互斥的软件实现方法和硬件实现方法)
318 |
319 | ### 3. 信号量
320 |
321 | (用信号量实现进程互斥 实现进程同步 实现进程前驱关系)
322 |
323 | 信号量(Semaphore)是一个整型变量,可以对其执行 down 和 up 操作,也就是常见的 P 和 V 操作。
324 |
325 | - **down** : 如果信号量大于 0 ,执行 -1 操作;如果信号量等于 0,进程睡眠,等待信号量大于 0;
326 | - **up** :对信号量执行 +1 操作,唤醒睡眠的进程让其完成 down 操作。
327 |
328 | down 和 up 操作需要被设计成原语,不可分割,通常的做法是在执行这些操作的时候屏蔽中断。
329 |
330 | 如果信号量的取值只能为 0 或者 1,那么就成为了 **互斥量(Mutex)** ,0 表示临界区已经加锁,1 表示临界区解锁。
331 |
332 | ```c
333 | typedef int semaphore;
334 | semaphore mutex = 1;
335 | void P1() {
336 | down(&mutex);
337 | // 临界区
338 | up(&mutex);
339 | }
340 |
341 | void P2() {
342 | down(&mutex);
343 | // 临界区
344 | up(&mutex);
345 | }
346 | ```
347 |
348 | \ **使用信号量实现生产者-消费者问题** \ \
349 |
350 | 问题描述:使用一个缓冲区来保存物品,只有缓冲区没有满,生产者才可以放入物品;只有缓冲区不为空,消费者才可以拿走物品。
351 |
352 | 因为缓冲区属于临界资源,因此需要使用一个互斥量 mutex 来控制对缓冲区的互斥访问。
353 |
354 | 为了同步生产者和消费者的行为,需要记录缓冲区中物品的数量。数量可以使用信号量来进行统计,这里需要使用两个信号量:empty 记录空缓冲区的数量,full 记录满缓冲区的数量。其中,empty 信号量是在生产者进程中使用,当 empty 不为 0 时,生产者才可以放入物品;full 信号量是在消费者进程中使用,当 full 信号量不为 0 时,消费者才可以取走物品。
355 |
356 | 注意,不能先对缓冲区进行加锁,再测试信号量。也就是说,不能先执行 down(mutex) 再执行 down(empty)。如果这么做了,那么可能会出现这种情况:生产者对缓冲区加锁后,执行 down(empty) 操作,发现 empty = 0,此时生产者睡眠。消费者不能进入临界区,因为生产者对缓冲区加锁了,消费者就无法执行 up(empty) 操作,empty 永远都为 0,导致生产者永远等待下,不会释放锁,消费者因此也会永远等待下去。(导致死锁 ) (P应该将导致互斥的信号量放到同步的信号量之后)
357 |
358 | ```c
359 | #define N 100
360 | typedef int semaphore;
361 | semaphore mutex = 1;
362 | semaphore empty = N;
363 | semaphore full = 0;
364 |
365 | void producer() {
366 | while(TRUE) {
367 | int item = produce_item();
368 | down(&empty);
369 | down(&mutex);
370 | insert_item(item);
371 | up(&mutex);
372 | up(&full);
373 | }
374 | }
375 |
376 | void consumer() {
377 | while(TRUE) {
378 | down(&full);
379 | down(&mutex);
380 | int item = remove_item();
381 | consume_item(item);
382 | up(&mutex);
383 | up(&empty);
384 | }
385 | }
386 | ```
387 |
388 | ### 4. 管程
389 |
390 | 使用信号量机制实现的生产 者消费者问题需要客户端代码做很多控制,而管程把控制的代码独立出来,不仅不容易出错,也使得客户端代码调用更容易。 (目的无非就是要更方便地实现进程互斥和同步)
391 |
392 | c 语言不支持管程,下面的示例代码使用了类 Pascal 语言来描述管程。示例代码的管程提供了 insert() 和 remove() 方法,客户端代码通过调用这两个方法来解决生产者-消费者问题。
393 |
394 | ```pascal
395 | monitor ProducerConsumer
396 | integer i;
397 | condition c;
398 |
399 | procedure insert();
400 | begin
401 | // ...
402 | end;
403 |
404 | procedure remove();
405 | begin
406 | // ...
407 | end;
408 | end monitor;
409 | ```
410 |
411 | 管程有一个重要特性:在一个时刻只能有一个进程使用管程。进程在无法继续执行的时候不能一直占用管程,否则其它进程永远不能使用管程。
412 |
413 | 管程引入了 **条件变量** 以及相关的操作:**wait()** 和 **signal()** 来实现同步操作。对条件变量执行 wait() 操作会导致调用进程阻塞,把管程让出来给另一个进程持有。signal() 操作用于唤醒被阻塞的进程。
414 |
415 | **使用管程实现生产者-消费者问题**
416 |
417 | ```pascal
418 | // 管程
419 | monitor ProducerConsumer
420 | condition full, empty;
421 | integer count := 0;
422 | condition c;
423 |
424 | procedure insert(item: integer);
425 | begin
426 | if count = N then wait(full);
427 | insert_item(item);
428 | count := count + 1;
429 | if count = 1 then signal(empty);
430 | end;
431 |
432 | function remove: integer;
433 | begin
434 | if count = 0 then wait(empty);
435 | remove = remove_item;
436 | count := count - 1;
437 | if count = N -1 then signal(full);
438 | end;
439 | end monitor;
440 |
441 | // 生产者客户端
442 | procedure producer
443 | begin
444 | while true do
445 | begin
446 | item = produce_item;
447 | ProducerConsumer.insert(item);
448 | end
449 | end;
450 |
451 | // 消费者客户端
452 | procedure consumer
453 | begin
454 | while true do
455 | begin
456 | item = ProducerConsumer.remove;
457 | consume_item(item);
458 | end
459 | end;
460 | ```
461 |
462 | ## 经典同步问题
463 |
464 | 生产者和消费者问题前面已经讨论过了。
465 |
466 | ### 1. 哲学家进餐问题
467 |
468 |
469 |
470 | 五个哲学家围着一张圆桌,每个哲学家面前放着食物。哲学家的生活有两种交替活动:吃饭以及思考。当一个哲学家吃饭时,需要先拿起自己左右两边的两根筷子,并且一次只能拿起一根筷子。
471 |
472 | 下面是一种错误的解法,如果所有哲学家同时拿起左手边的筷子,那么所有哲学家都在等待其它哲学家吃完并释放自己手中的筷子,导致死锁。
473 |
474 | ```c
475 | #define N 5
476 |
477 | void philosopher(int i) {
478 | while(TRUE) {
479 | think();
480 | take(i); // 拿起左边的筷子
481 | take((i+1)%N); // 拿起右边的筷子
482 | eat();
483 | put(i);
484 | put((i+1)%N);
485 | }
486 | }
487 | ```
488 |
489 | 为了防止死锁的发生,可以设置两个条件:
490 |
491 | - 必须同时拿起左右两根筷子;
492 | - 只有在两个邻居都没有进餐的情况下才允许进餐。
493 |
494 | ```c
495 | #define N 5
496 | #define LEFT (i + N - 1) % N // 左邻居
497 | #define RIGHT (i + 1) % N // 右邻居
498 | #define THINKING 0
499 | #define HUNGRY 1
500 | #define EATING 2
501 | typedef int semaphore;
502 | int state[N]; // 跟踪每个哲学家的状态
503 | semaphore mutex = 1; // 临界区的互斥,临界区是 state 数组,对其修改需要互斥
504 | semaphore s[N]; // 每个哲学家一个信号量
505 |
506 | void philosopher(int i) {
507 | while(TRUE) {
508 | think(i);
509 | take_two(i);
510 | eat(i);
511 | put_two(i);
512 | }
513 | }
514 |
515 | void take_two(int i) {
516 | down(&mutex);
517 | state[i] = HUNGRY;
518 | check(i);
519 | up(&mutex);
520 | down(&s[i]); // 只有收到通知之后才可以开始吃,否则会一直等下去
521 | }
522 |
523 | void put_two(i) {
524 | down(&mutex);
525 | state[i] = THINKING;
526 | check(LEFT); // 尝试通知左右邻居,自己吃完了,你们可以开始吃了
527 | check(RIGHT);
528 | up(&mutex);
529 | }
530 |
531 | void eat(int i) {
532 | down(&mutex);
533 | state[i] = EATING;
534 | up(&mutex);
535 | }
536 |
537 | // 检查两个邻居是否都没有用餐,如果是的话,就 up(&s[i]),使得 down(&s[i]) 能够得到通知并继续执行
538 | void check(i) {
539 | if(state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] !=EATING) {
540 | state[i] = EATING;
541 | up(&s[i]);
542 | }
543 | }
544 | ```
545 |
546 | ### 2. 读者-写者问题
547 |
548 | 允许多个进程同时对数据进行读操作,但是不允许读和写以及写和写操作同时发生。
549 |
550 | 一个整型变量 count 记录在对数据进行读操作的进程数量,一个互斥量 count_mutex 用于对 count 加锁,一个互斥量 data_mutex 用于对读写的数据加锁。
551 |
552 | ```c
553 | typedef int semaphore;
554 | semaphore count_mutex = 1;
555 | semaphore data_mutex = 1;
556 | int count = 0;
557 |
558 | void reader() {
559 | while(TRUE) {
560 | down(&count_mutex);
561 | count++;
562 | if(count == 1) down(&data_mutex); // 第一个读者需要对数据进行加锁,防止写进程访问
563 | up(&count_mutex);
564 | read();
565 | down(&count_mutex);
566 | count--;
567 | if(count == 0) up(&data_mutex);
568 | up(&count_mutex);
569 | }
570 | }
571 |
572 | void writer() {
573 | while(TRUE) {
574 | down(&data_mutex);
575 | write();
576 | up(&data_mutex);
577 | }
578 | }
579 | ```
580 |
581 | 以下内容由 [@Bandi Yugandhar](https://github.com/yugandharbandi) 提供。
582 |
583 | The first case may result Writer to starve. This case favous Writers i.e no writer, once added to the queue, shall be kept waiting longer than absolutely necessary(only when there are readers that entered the queue before the writer).
584 |
585 | ```c
586 | int readcount, writecount; //(initial value = 0)
587 | semaphore rmutex, wmutex, readLock, resource; //(initial value = 1)
588 |
589 | //READER
590 | void reader() {
591 |
592 | down(&readLock); // reader is trying to enter
593 | down(&rmutex); // lock to increase readcount
594 | readcount++;
595 | if (readcount == 1)
596 | down(&resource); //if you are the first reader then lock the resource
597 | up(&rmutex); //release for other readers
598 | up(&readLock); //Done with trying to access the resource
599 |
600 |
601 | //reading is performed
602 |
603 |
604 | down(&rmutex); //reserve exit section - avoids race condition with readers
605 | readcount--; //indicate you're leaving
606 | if (readcount == 0) //checks if you are last reader leaving
607 | up(&resource); //if last, you must release the locked resource
608 | up(&rmutex); //release exit section for other readers
609 | }
610 |
611 | //WRITER
612 | void writer() {
613 |
614 | down(&wmutex); //reserve entry section for writers - avoids race conditions
615 | writecount++; //report yourself as a writer entering
616 | if (writecount == 1) //checks if you're first writer
617 | down(&readLock); //if you're first, then you must lock the readers out. Prevent them from trying to enter CS
618 | up(&wmutex); //release entry section
619 |
620 |
621 | down(&resource); //reserve the resource for yourself - prevents other writers from simultaneously editing the shared resource
622 | //writing is performed
623 | up(&resource); //release file
624 |
625 |
626 | down(&wmutex); //reserve exit section
627 | writecount--; //indicate you're leaving
628 | if (writecount == 0) //checks if you're the last writer
629 | up(&readLock); //if you're last writer, you must unlock the readers. Allows them to try enter CS for reading
630 | up(&wmutex); //release exit section
631 | }
632 | ```
633 |
634 | We can observe that every reader is forced to acquire ReadLock. On the otherhand, writers doesn’t need to lock individually. Once the first writer locks the ReadLock, it will be released only when there is no writer left in the queue.
635 |
636 | From the both cases we observed that either reader or writer has to starve. Below solutionadds the constraint that no thread shall be allowed to starve; that is, the operation of obtaining a lock on the shared data will always terminate in a bounded amount of time.
637 |
638 | ```source-c
639 | int readCount; // init to 0; number of readers currently accessing resource
640 |
641 | // all semaphores initialised to 1
642 | Semaphore resourceAccess; // controls access (read/write) to the resource
643 | Semaphore readCountAccess; // for syncing changes to shared variable readCount
644 | Semaphore serviceQueue; // FAIRNESS: preserves ordering of requests (signaling must be FIFO)
645 |
646 | void writer()
647 | {
648 | down(&serviceQueue); // wait in line to be servicexs
649 | //
650 | down(&resourceAccess); // request exclusive access to resource
651 | //
652 | up(&serviceQueue); // let next in line be serviced
653 |
654 | //
655 | writeResource(); // writing is performed
656 | //
657 |
658 | //
659 | up(&resourceAccess); // release resource access for next reader/writer
660 | //
661 | }
662 |
663 | void reader()
664 | {
665 | down(&serviceQueue); // wait in line to be serviced
666 | down(&readCountAccess); // request exclusive access to readCount
667 | //
668 | if (readCount == 0) // if there are no readers already reading:
669 | down(&resourceAccess); // request resource access for readers (writers blocked)
670 | readCount++; // update count of active readers
671 | //
672 | up(&serviceQueue); // let next in line be serviced
673 | up(&readCountAccess); // release access to readCount
674 |
675 | //
676 | readResource(); // reading is performed
677 | //
678 |
679 | down(&readCountAccess); // request exclusive access to readCount
680 | //
681 | readCount--; // update count of active readers
682 | if (readCount == 0) // if there are no readers left:
683 | up(&resourceAccess); // release resource access for all
684 | //
685 | up(&readCountAccess); // release access to readCount
686 | }
687 |
688 | ```
689 |
690 | ## 进程通信
691 |
692 | 进程同步与进程通信很容易混淆,它们的区别在于:
693 |
694 | - 进程同步:控制多个进程按一定顺序执行;
695 | - 进程通信:进程间传输信息。
696 |
697 | 进程通信是一种手段,而进程同步是一种目的。也可以说,为了能够达到进程同步的目的,需要让进程进行通信,传输一些进程同步所需要的信息。
698 |
699 | ### 1. 管道
700 |
701 | 是指用于连续读写进程的一个共享文件。其实就是再内存中开辟一个大小固定的缓冲区。
702 |
703 | (各进程要互地访问管道)
704 |
705 | 管道是通过调用 pipe 函数创建的,fd[0] 用于读,fd[1] 用于写。
706 |
707 | ```c
708 | #include
709 | int pipe(int fd[2]);
710 | ```
711 |
712 | 它具有以下限制:
713 |
714 | - 只支持半双工通信(单向交替传输);
715 | - 只能在父子进程或者兄弟进程中使用。
716 |
717 |
718 |
719 | ### 2. FIFO
720 |
721 | 也称为命名管道,去除了管道只能在父子进程中使用的限制。
722 |
723 | ```c
724 | #include
725 | int mkfifo(const char *path, mode_t mode);
726 | int mkfifoat(int fd, const char *path, mode_t mode);
727 | ```
728 |
729 | FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户进程和服务器进程之间传递数据。
730 |
731 |
732 |
733 | ### 3. 消息队列
734 |
735 | 相比于 FIFO,消息队列具有以下优点:
736 |
737 | - 消息队列可以独立于读写进程存在,从而避免了 FIFO 中同步管道的打开和关闭时可能产生的困难;
738 | - 避免了 FIFO 的同步阻塞问题,不需要进程自己提供同步方法;
739 | - 读进程可以根据消息类型有选择地接收消息,而不像 FIFO 那样只能默认地接收。
740 |
741 | ### 4. 信号量
742 |
743 | 它是一个计数器,用于为多个进程提供对共享数据对象的访问。
744 |
745 | ### 5. 共享存储
746 |
747 | 允许多个进程共享一个给定的存储区。因为数据不需要在进程之间复制,所以这是最快的一种 IPC。(多个进程对共享空间的访问必须是互斥的)
748 |
749 | 需要使用信号量用来同步对共享存储的访问。
750 |
751 | 多个进程可以将同一个文件映射到它们的地址空间从而实现共享内存。另外 XSI 共享内存不是使用文件,而是使用内存的匿名段。
752 |
753 | ### 6. 套接字
754 |
755 | 与其它通信机制不同的是,它可用于不同机器间的进程通信。
756 |
757 | # 计算机操作系统 - 死锁
758 |
759 | * [计算机操作系统 - 死锁](#计算机操作系统---死锁)
760 | * [必要条件](#必要条件)
761 | * [处理方法](#处理方法)
762 | * [鸵鸟策略](#鸵鸟策略)
763 | * [死锁检测与死锁恢复](#死锁检测与死锁恢复)
764 | * [1. 每种类型一个资源的死锁检测](#1-每种类型一个资源的死锁检测)
765 | * [2. 每种类型多个资源的死锁检测](#2-每种类型多个资源的死锁检测)
766 | * [3. 死锁恢复](#3-死锁恢复)
767 | * [死锁预防](#死锁预防)
768 | * [1. 破坏互斥条件](#1-破坏互斥条件)
769 | * [2. 破坏占有和等待条件](#2-破坏占有和等待条件)
770 | * [3. 破坏不可抢占条件](#3-破坏不可抢占条件)
771 | * [4. 破坏环路等待](#4-破坏环路等待)
772 | * [死锁避免](#死锁避免)
773 | * [1. 安全状态](#1-安全状态)
774 | * [2. 单个资源的银行家算法](#2-单个资源的银行家算法)
775 | * [3. 多个资源的银行家算法](#3-多个资源的银行家算法)
776 |
777 |
778 |
779 | ## 必要条件
780 |
781 |
782 |
783 | - 互斥:每个资源要么已经分配给了一个进程,要么就是可用的。
784 | - 占有和等待:已经得到了某个资源的进程可以再请求新的资源。
785 | - 不可抢占:已经分配给一个进程的资源不能强制性地被抢占,它只能被占有它的进程显式地释放。
786 | - 环路等待:有两个或者两个以上的进程组成一条环路,该环路中的每个进程都在等待下一个进程所占有的资源。
787 |
788 | ## 处理方法
789 |
790 | 主要有以下四种方法:
791 |
792 | - 鸵鸟策略
793 | - 死锁检测与死锁恢复
794 | - 死锁预防
795 | - 死锁避免
796 |
797 | ## 鸵鸟策略
798 |
799 | 把头埋在沙子里,假装根本没发生问题。
800 |
801 | 因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。
802 |
803 | 当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。
804 |
805 | 大多数操作系统,包括 Unix,Linux 和 Windows,处理死锁问题的办法仅仅是忽略它。
806 |
807 | ## 死锁检测与死锁恢复
808 |
809 | 不试图阻止死锁,而是当检测到死锁发生时,采取措施进行恢复。
810 |
811 | ### 1. 每种类型一个资源的死锁检测
812 |
813 |
814 |
815 | 上图为资源分配图,其中方框表示资源,圆圈表示进程。资源指向进程表示该资源已经分配给该进程,进程指向资源表示进程请求获取该资源。
816 |
817 | 图 a 可以抽取出环,如图 b,它满足了环路等待条件,因此会发生死锁。
818 |
819 | 每种类型一个资源的死锁检测算法是通过检测有向图是否存在环来实现,从一个节点出发进行深度优先搜索,对访问过的节点进行标记,如果访问了已经标记的节点,就表示有向图存在环,也就是检测到死锁的发生。
820 |
821 | ### 2. 每种类型多个资源的死锁检测
822 |
823 |
824 |
825 | 上图中,有三个进程四个资源,每个数据代表的含义如下:
826 |
827 | - E 向量:资源总量
828 | - A 向量:资源剩余量
829 | - C 矩阵:每个进程所拥有的资源数量,每一行都代表一个进程拥有资源的数量
830 | - R 矩阵:每个进程请求的资源数量
831 |
832 | 进程 P1 和 P2 所请求的资源都得不到满足,只有进程 P3 可以,让 P3 执行,之后释放 P3 拥有的资源,此时 A = (2 2 2 0)。P2 可以执行,执行后释放 P2 拥有的资源,A = (4 2 2 1) 。P1 也可以执行。所有进程都可以顺利执行,没有死锁。
833 |
834 | 算法总结如下:
835 |
836 | 每个进程最开始时都不被标记,执行过程有可能被标记。当算法结束时,任何没有被标记的进程都是死锁进程。
837 |
838 | 1. 寻找一个没有标记的进程 Pi ,它所请求的资源小于等于 A。
839 | 2. 如果找到了这样一个进程,那么将 C 矩阵的第 i 行向量加到 A 中,标记该进程,并转回 1。
840 | 3. 如果没有这样一个进程,算法终止。
841 |
842 | ### 3. 死锁恢复
843 |
844 | - 利用抢占恢复
845 | - 利用回滚恢复
846 | - 通过杀死进程恢复
847 |
848 | ## 死锁预防
849 |
850 | 在程序运行之前预防发生死锁。
851 |
852 | ### 1. 破坏互斥条件
853 |
854 | 例如假脱机打印机技术允许若干个进程同时输出,唯一真正请求物理打印机的进程是打印机守护进程。
855 |
856 | ### 2. 破坏占有和等待条件
857 |
858 | 一种实现方式是规定所有进程在开始执行前请求所需要的全部资源。
859 |
860 | ### 3. 破坏不可抢占条件
861 |
862 | ### 4. 破坏环路等待
863 |
864 | 给资源统一编号,进程只能按编号顺序来请求资源。
865 |
866 | ## 死锁避免
867 |
868 | 在程序运行时避免发生死锁。
869 |
870 | ### 1. 安全状态
871 |
872 |
873 |
874 | 图 a 的第二列 Has 表示已拥有的资源数,第三列 Max 表示总共需要的资源数,Free 表示还有可以使用的资源数。从图 a 开始出发,先让 B 拥有所需的所有资源(图 b),运行结束后释放 B,此时 Free 变为 5(图 c);接着以同样的方式运行 C 和 A,使得所有进程都能成功运行,因此可以称图 a 所示的状态时安全的。
875 |
876 | 定义:如果没有死锁发生,并且即使所有进程突然请求对资源的最大需求,也仍然存在某种调度次序能够使得每一个进程运行完毕,则称该状态是安全的。
877 |
878 | 安全状态的检测与死锁的检测类似,因为安全状态必须要求不能发生死锁。下面的银行家算法与死锁检测算法非常类似,可以结合着做参考对比。
879 |
880 | ### 2. 单个资源的银行家算法
881 |
882 | 一个小城镇的银行家,他向一群客户分别承诺了一定的贷款额度,算法要做的是判断对请求的满足是否会进入不安全状态,如果是,就拒绝请求;否则予以分配。
883 |
884 |
885 |
886 | 上图 c 为不安全状态,因此算法会拒绝之前的请求,从而避免进入图 c 中的状态。
887 |
888 | ### 3. 多个资源的银行家算法
889 |
890 |
891 |
892 | 上图中有五个进程,四个资源。左边的图表示已经分配的资源,右边的图表示还需要分配的资源。最右边的 E、P 以及 A 分别表示:总资源、已分配资源以及可用资源,注意这三个为向量,而不是具体数值,例如 A=(1020),表示 4 个资源分别还剩下 1/0/2/0。
893 |
894 | 检查一个状态是否安全的算法如下:
895 |
896 | - 查找右边的矩阵是否存在一行小于等于向量 A。如果不存在这样的行,那么系统将会发生死锁,状态是不安全的。
897 | - 假若找到这样一行,将该进程标记为终止,并将其已分配资源加到 A 中。
898 | - 重复以上两步,直到所有进程都标记为终止,则状态时安全的。
899 |
900 | 如果一个状态不是安全的,需要拒绝进入这个状态。
901 |
902 | # 计算机操作系统 - 内存管理
903 |
904 | * [计算机操作系统 - 内存管理](#计算机操作系统---内存管理)
905 | * [虚拟内存](#虚拟内存)
906 | * [分页系统地址映射](#分页系统地址映射)
907 | * [页面置换算法](#页面置换算法)
908 | * [1. 最佳](#1-最佳)
909 | * [2. 最近最久未使用](#2-最近最久未使用)
910 | * [3. 最近未使用](#3-最近未使用)
911 | * [4. 先进先出](#4-先进先出)
912 | * [5. 第二次机会算法](#5-第二次机会算法)
913 | * [6. 时钟](#6-时钟)
914 | * [分段](#分段)
915 | * [段页式](#段页式)
916 | * [分页与分段的比较](#分页与分段的比较)
917 |
918 |
919 |
920 | ## 虚拟内存
921 |
922 | 虚拟内存的目的是为了让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存。
923 |
924 | 为了更好的管理内存,操作系统将内存抽象成地址空间。每个程序拥有自己的地址空间,这个地址空间被分割成多个块,每一块称为一页。这些页被映射到物理内存,但不需要映射到连续的物理内存,也不需要所有页都必须在物理内存中。当程序引用到不在物理内存中的页时,由硬件执行必要的映射,将缺失的部分装入物理内存并重新执行失败的指令。
925 |
926 | 从上面的描述中可以看出,虚拟内存允许程序不用将地址空间中的每一页都映射到物理内存,也就是说一个程序不需要全部调入内存就可以运行,这使得有限的内存运行大程序成为可能。例如有一台计算机可以产生 16 位地址,那么一个程序的地址空间范围是 0\~64K。该计算机只有 32KB 的物理内存,虚拟内存技术允许该计算机运行一个 64K 大小的程序。
927 |
928 |
929 |
930 | ## 分页系统地址映射
931 |
932 | 内存管理单元(MMU)管理着地址空间和物理内存的转换,其中的页表(Page table)存储着页(程序地址空间)和页框(物理内存空间)的映射表。
933 |
934 | 一个虚拟地址分成两个部分,一部分存储页面号,一部分存储偏移量。
935 |
936 | 下图的页表存放着 16 个页,这 16 个页需要用 4 个比特位来进行索引定位。例如对于虚拟地址(0010 000000000100),前 4 位是存储页面号 2,读取表项内容为(110 1),页表项最后一位表示是否存在于内存中,1 表示存在。后 12 位存储偏移量。这个页对应的页框的地址为 (110 000000000100)。
937 |
938 |
939 |
940 | ## 页面置换算法
941 |
942 | 在程序运行过程中,如果要访问的页面不在内存中,就发生缺页中断从而将该页调入内存中。此时如果内存已无空闲空间,系统必须从内存中调出一个页面到磁盘对换区中来腾出空间。(请求调页、页面置换、需要修改请求页表中新增的表项)
943 |
944 | 页面置换算法和缓存淘汰策略类似,可以将内存看成磁盘的缓存。在缓存系统中,缓存的大小有限,当有新的缓存到达时,需要淘汰一部分已经存在的缓存,这样才有空间存放新的缓存数据。
945 |
946 | 页面置换算法的主要目标是使页面置换频率最低(也可以说缺页率最低)。
947 |
948 | ### 1. 最佳
949 |
950 | > OPT, Optimal replacement algorithm
951 |
952 | 所选择的被换出的页面将是最长时间内不再被访问,通常可以保证获得最低的缺页率。
953 |
954 | 是一种理论上的算法,因为无法知道一个页面多长时间不再被访问。
955 |
956 | 举例:一个系统为某进程分配了三个物理块,并有如下页面引用序列:
957 |
958 | ```html
959 | 7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1
960 | ```
961 |
962 | 开始运行时,先将 7, 0, 1 三个页面装入内存。当进程要访问页面 2 时,产生缺页中断,会将页面 7 换出,因为页面 7 再次被访问的时间最长。
963 |
964 | ### 2. 最近最久未使用
965 |
966 | > LRU, Least Recently Used
967 |
968 | 虽然无法知道将来要使用的页面情况,但是可以知道过去使用页面的情况。LRU 将最近最久未使用的页面换出。
969 |
970 | 为了实现 LRU,需要在内存中维护一个所有页面的链表。当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面是最近最久未访问的。
971 |
972 | 因为每次访问都需要更新链表,因此这种方式实现的 LRU 代价很高。
973 |
974 | ```html
975 | 4,7,0,7,1,0,1,2,1,2,6
976 | ```
977 |
978 |
979 | ### 3. 最近未使用
980 |
981 | > NRU, Not Recently Used (时钟)
982 |
983 | 每个页面都有两个状态位:R 与 M,当页面被访问时设置页面的 R=1,当页面被修改时设置 M=1。其中 R 位会定时被清零。可以将页面分成以下四类:
984 |
985 | - R=0,M=0
986 | - R=0,M=1
987 | - R=1,M=0
988 | - R=1,M=1
989 |
990 | 当发生缺页中断时,NRU 算法随机地从类编号最小的非空类中挑选一个页面将它换出。
991 |
992 | NRU 优先换出已经被修改的脏页面(R=0,M=1),而不是被频繁使用的干净页面(R=1,M=0)。
993 |
994 | ### 4. 先进先出
995 |
996 | > FIFO, First In First Out
997 |
998 | 选择换出的页面是最先进入的页面。
999 |
1000 | 该算法会将那些经常被访问的页面换出,导致缺页率升高。
1001 |
1002 | (当为进程分配的物理块数增大时,缺页次数不减反增的现象 belady异常)
1003 |
1004 | ### 5. 第二次机会算法
1005 |
1006 | FIFO 算法可能会把经常使用的页面置换出去,为了避免这一问题,对该算法做一个简单的修改:
1007 |
1008 | 当页面被访问 (读或写) 时设置该页面的 R 位为 1。需要替换的时候,检查最老页面的 R 位。如果 R 位是 0,那么这个页面既老又没有被使用,可以立刻置换掉;如果是 1,就将 R 位清 0,并把该页面放到链表的尾端,修改它的装入时间使它就像刚装入的一样,然后继续从链表的头部开始搜索。
1009 |
1010 |
1011 |
1012 | ### 6. 时钟
1013 |
1014 | > Clock
1015 |
1016 | 第二次机会算法需要在链表中移动页面,降低了效率。时钟算法使用环形链表将页面连接起来,再使用一个指针指向最老的页面。
1017 |
1018 |
1019 |
1020 |
1021 |
1022 |
1023 |
1024 |
1025 |
1026 | (下面这部分是内存的非连续分配管理方式)
1027 |
1028 | ## 分段
1029 |
1030 | 虚拟内存采用的是分页技术,也就是将地址空间划分成固定大小的页,每一页再与内存进行映射。
1031 |
1032 | 下图为一个编译器在编译过程中建立的多个表,有 4 个表是动态增长的,如果使用分页系统的一维地址空间,动态增长的特点会导致覆盖问题的出现。
1033 |
1034 |
1035 |
1036 | 分段的做法是把每个表分成段,一个段构成一个独立的地址空间。每个段的长度可以不同,并且可以动态增长。
1037 |
1038 |
1039 |
1040 | ## 段页式
1041 |
1042 | 程序的地址空间划分成多个拥有独立地址空间的段,每个段上的地址空间划分成大小相同的页。这样既拥有分段系统的共享和保护,又拥有分页系统的虚拟内存功能。
1043 |
1044 | ## 分页与分段的比较
1045 |
1046 | - 对程序员的透明性:分页透明,但是分段需要程序员显式划分每个段。
1047 |
1048 | - 地址空间的维度:分页是一维地址空间,分段是二维的。
1049 |
1050 | - 大小是否可以改变:页的大小不可变,段的大小可以动态改变。
1051 |
1052 | - 出现的原因:分页主要用于实现虚拟内存,从而获得更大的地址空间;分段主要是为了使程序和数据可以被划分为逻辑上独立的地址空间并且有助于共享和保护。
1053 |
1054 | # 计算机操作系统 - 设备管理
1055 |
1056 | * [计算机操作系统 - 设备管理](#计算机操作系统---设备管理)
1057 | * [磁盘结构](#磁盘结构)
1058 | * [磁盘调度算法](#磁盘调度算法)
1059 | * [1. 先来先服务](#1-先来先服务)
1060 | * [2. 最短寻道时间优先](#2-最短寻道时间优先)
1061 | * [3. 电梯算法](#3-电梯算法)
1062 |
1063 |
1064 | ## 磁盘结构
1065 |
1066 | (可以用 柱面号,盘面号,扇区号定位磁盘中特定的扇区)
1067 |
1068 | - 盘面(Platter):一个磁盘有多个盘面;
1069 | - 磁道(Track):盘面上的圆形带状区域,一个盘面可以有多个磁道;
1070 | - 扇区(Track Sector):磁道上的一个弧段,一个磁道可以有多个扇区,它是最小的物理储存单位,目前主要有 512 bytes 与 4 K 两种大小;
1071 | - 磁头(Head):与盘面非常接近,能够将盘面上的磁场转换为电信号(读),或者将电信号转换为盘面的磁场(写);
1072 | - 制动手臂(Actuator arm):用于在磁道之间移动磁头;
1073 | - 主轴(Spindle):使整个盘面转动。
1074 |
1075 |
1076 |
1077 | ## 磁盘调度算法
1078 |
1079 | 读写一个磁盘块的时间的影响因素有:
1080 |
1081 | - 旋转时间(主轴转动盘面,使得磁头移动到适当的扇区上)
1082 |
1083 | - 寻道时间(制动手臂移动,使得磁头移动到适当的磁道上)
1084 |
1085 | - 实际的数据传输时间
1086 |
1087 | (旋转时间和实际的数据传输时间是磁盘的固有属性,无法通过算法来优化)
1088 |
1089 | 其中,寻道时间最长,因此磁盘调度的主要目标是使磁盘的平均寻道时间最短。
1090 |
1091 | ### 1. 先来先服务
1092 |
1093 | > FCFS, First Come First Served
1094 |
1095 | 按照磁盘请求的顺序进行调度。
1096 |
1097 | 优点是公平和简单。缺点也很明显,因为未对寻道做任何优化,使平均寻道时间可能较长。
1098 |
1099 | ### 2. 最短寻道时间优先
1100 |
1101 | > SSTF, Shortest Seek Time First
1102 |
1103 | 优先调度与当前磁头所在磁道距离最近的磁道。
1104 |
1105 | 虽然平均寻道时间比较低,但是不够公平。如果新到达的磁道请求总是比一个在等待的磁道请求近,那么在等待的磁道请求会一直等待下去,也就是出现饥饿现象。具体来说,两端的磁道请求更容易出现饥饿现象。
1106 |
1107 |
1108 |
1109 | ### 3. 电梯算法
1110 |
1111 | > SCAN
1112 |
1113 | 电梯总是保持一个方向运行,直到该方向没有请求为止,然后改变运行方向。
1114 |
1115 | 电梯算法(扫描算法)和电梯的运行过程类似,总是按一个方向来进行磁盘调度,直到该方向上没有未完成的磁盘请求,然后改变方向。
1116 |
1117 | 因为考虑了移动方向,因此所有的磁盘请求都会被满足,解决了 SSTF 的饥饿问题。
1118 |
1119 |
1120 |
1121 | # 计算机操作系统 - 链接
1122 |
1123 | * [计算机操作系统 - 链接](#计算机操作系统---链接)
1124 | * [编译系统](#编译系统)
1125 | * [静态链接](#静态链接)
1126 | * [目标文件](#目标文件)
1127 | * [动态链接](#动态链接)
1128 |
1129 |
1130 |
1131 | ## 编译系统
1132 |
1133 |
1134 | 以下是一个 hello.c 程序:
1135 |
1136 | ```c
1137 | #include
1138 |
1139 | int main()
1140 | {
1141 | printf("hello, world\n");
1142 | return 0;
1143 | }
1144 | ```
1145 |
1146 | 在 Unix 系统上,由编译器把源文件转换为目标文件。
1147 |
1148 | ```bash
1149 | gcc -o hello hello.c
1150 | ```
1151 |
1152 | 这个过程大致如下:
1153 |
1154 |
1155 |
1156 | - 预处理阶段:处理以 # 开头的预处理命令;
1157 | - 编译阶段:翻译成汇编文件;
1158 | - 汇编阶段:将汇编文件翻译成可重定位目标文件;
1159 | - 链接阶段:将可重定位目标文件和 printf.o 等单独预编译好的目标文件进行合并,得到最终的可执行目标文件。
1160 |
1161 | ## 静态链接
1162 |
1163 | 静态链接器以一组可重定位目标文件为输入,生成一个完全链接的可执行目标文件作为输出。链接器主要完成以下两个任务:
1164 |
1165 | - 符号解析:每个符号对应于一个函数、一个全局变量或一个静态变量,符号解析的目的是将每个符号引用与一个符号定义关联起来。
1166 | - 重定位:链接器通过把每个符号定义与一个内存位置关联起来,然后修改所有对这些符号的引用,使得它们指向这个内存位置。
1167 |
1168 |
1169 |
1170 | ## 目标文件
1171 |
1172 | - 可执行目标文件:可以直接在内存中执行;
1173 | - 可重定位目标文件:可与其它可重定位目标文件在链接阶段合并,创建一个可执行目标文件;
1174 | - 共享目标文件:这是一种特殊的可重定位目标文件,可以在运行时被动态加载进内存并链接;
1175 |
1176 | ## 动态链接
1177 |
1178 | 静态库有以下两个问题:
1179 |
1180 | - 当静态库更新时那么整个程序都要重新进行链接;
1181 | - 对于 printf 这种标准函数库,如果每个程序都要有代码,这会极大浪费资源。
1182 |
1183 | 共享库是为了解决静态库的这两个问题而设计的,在 Linux 系统中通常用 .so 后缀来表示,Windows 系统上它们被称为 DLL。它具有以下特点:
1184 |
1185 | - 在给定的文件系统中一个库只有一个文件,所有引用该库的可执行目标文件都共享这个文件,它不会被复制到引用它的可执行文件中;
1186 | - 在内存中,一个共享库的 .text 节(已编译程序的机器代码)的一个副本可以被不同的正在运行的进程共享。
1187 |
1188 |
1189 |
--------------------------------------------------------------------------------
/小曾Linux私房菜.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzzzzzzzyt/JavaLearningNotes/d53263b10ab6655900423e19437efb3936f4a223/小曾Linux私房菜.pdf
--------------------------------------------------------------------------------
/常用命令合集.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzzzzzzzyt/JavaLearningNotes/d53263b10ab6655900423e19437efb3936f4a223/常用命令合集.pdf
--------------------------------------------------------------------------------
/操作系统查漏补缺.md:
--------------------------------------------------------------------------------
1 | # 操作系统查漏补缺
2 |
3 |
4 |
5 | ==把小林coding的总结摘抄出来,方便之后直接进行回顾==
6 |
7 | # 硬件结构
8 |
9 | ## 2.1 CPU 是如何执行程序的?
10 |
11 | 最后我们再来回答开头的问题。
12 |
13 | > 64 位相比 32 位 CPU 的优势在哪吗?64 位 CPU 的计算性能一定比 32 位 CPU 高很多吗?
14 |
15 | 64 位相比 32 位 CPU 的优势主要体现在两个方面:
16 |
17 | - 64 位 CPU 可以一次计算超过 32 位的数字,而 32 位 CPU 如果要计算超过 32 位的数字,要分多步骤进行计算,效率就没那么高,但是大部分应用程序很少会计算那么大的数字,所以**只有运算大数字的时候,64 位 CPU 的优势才能体现出来,否则和 32 位 CPU 的计算性能相差不大**。
18 | - 64 位 CPU 可以**寻址更大的内存空间**,32 位 CPU 最大的寻址地址是 4G,即使你加了 8G 大小的内存,也还是只能寻址到 4G,而 64 位 CPU 最大寻址地址是 `2^64`,远超于 32 位 CPU 最大寻址地址的 `2^32`。
19 |
20 | > 你知道软件的 32 位和 64 位之间的区别吗?再来 32 位的操作系统可以运行在 64 位的电脑上吗?64 位的操作系统可以运行在 32 位的电脑上吗?如果不行,原因是什么?
21 |
22 | 64 位和 32 位软件,实际上代表指令是 64 位还是 32 位的:
23 |
24 | - 如果 32 位指令在 64 位机器上执行,需要一套兼容机制,就可以做到兼容运行了。但是**如果 64 位指令在 32 位机器上执行,就比较困难了,因为 32 位的寄存器存不下 64 位的指令**;
25 | - 操作系统其实也是一种程序,我们也会看到操作系统会分成 32 位操作系统、64 位操作系统,其代表意义就是操作系统中程序的指令是多少位,比如 64 位操作系统,指令也就是 64 位,因此不能装在 32 位机器上。
26 |
27 | 总之,硬件的 64 位和 32 位指的是 CPU 的位宽,软件的 64 位和 32 位指的是指令的位宽。
28 |
29 |
30 |
31 | ## 2.2 磁盘比内存慢几万倍?
32 |
33 | 各种存储器之间的关系,可以用我们在图书馆学习这个场景来理解。
34 |
35 | CPU 可以比喻成我们的大脑,我们当前正在思考和处理的知识的过程,就好比 CPU 中的**寄存器**处理数据的过程,速度极快,但是容量很小。而 CPU 中的 **L1-L3 Cache** 好比我们大脑中的短期记忆和长期记忆,需要小小花费点时间来调取数据并处理。
36 |
37 | 我们面前的桌子就相当于**内存**,能放下更多的书(数据),但是找起来和看起来就要花费一些时间,相比 CPU Cache 慢不少。而图书馆的书架相当于**硬盘**,能放下比内存更多的数据,但找起来就更费时间了,可以说是最慢的存储器设备了。
38 |
39 | 从 寄存器、CPU Cache,到内存、硬盘,这样一层层下来的存储器,访问速度越来越慢,存储容量越来越大,价格也越来越便宜,而且每个存储器只和相邻的一层存储器设备打交道,于是这样就形成了存储器的层次结构。
40 |
41 | 再来回答,开头的问题:那机械硬盘、固态硬盘、内存这三个存储器,到底和 `CPU L1 Cache` 相比速度差多少倍呢?
42 |
43 | CPU L1 Cache 随机访问延时是 1 纳秒,内存则是 100 纳秒,所以 **CPU L1 Cache 比内存快 100 倍左右**。
44 |
45 | SSD 随机访问延时是 150 微妙,所以 **CPU L1 Cache 比 SSD 快 150000 倍左右**。
46 |
47 | 最慢的机械硬盘随机访问延时已经高达 10 毫秒,我们来看看机械硬盘到底有多「龟速」:
48 |
49 | - **SSD 比机械硬盘快 70 倍左右;**
50 | - **内存比机械硬盘快 100000 倍左右;**
51 | - **CPU L1 Cache 比机械硬盘快 10000000 倍左右;**
52 |
53 | 我们把上述的时间比例差异放大后,就能非常直观感受到它们的性能差异了。如果 CPU 访问 L1 Cache 的缓存时间是 1 秒,那访问内存则需要大约 2 分钟,随机访问 SSD 里的数据则需要 1.7 天,访问机械硬盘那更久,长达近 4 个月。
54 |
55 | 可以发现,不同的存储器之间性能差距很大,构造存储器分级很有意义,分级的目的是要构造**缓存**体系。
56 |
57 |
58 |
59 |
60 |
61 | ## 2.3 如何写出让 CPU 跑得更快的代码?
62 |
63 | 由于随着计算机技术的发展,CPU 与 内存的访问速度相差越来越多,如今差距已经高达好几百倍了,所以 CPU 内部嵌入了 CPU Cache 组件,作为内存与 CPU 之间的缓存层,CPU Cache 由于离 CPU 核心很近,所以访问速度也是非常快的,但由于所需材料成本比较高,它不像内存动辄几个 GB 大小,而是仅有几十 KB 到 MB 大小。
64 |
65 | 当 CPU 访问数据的时候,先是访问 CPU Cache,如果缓存命中的话,则直接返回数据,就不用每次都从内存读取速度了。因此,缓存命中率越高,代码的性能越好。
66 |
67 | 但需要注意的是,当 CPU 访问数据时,如果 CPU Cache 没有缓存该数据,则会从内存读取数据,但是并不是只读一个数据,而是一次性读取一块一块的数据存放到 CPU Cache 中,之后才会被 CPU 读取。
68 |
69 | 内存地址映射到 CPU Cache 地址里的策略有很多种,其中比较简单是直接映射 Cache,它巧妙的把内存地址拆分成「索引 + 组标记 + 偏移量」的方式,使得我们可以将很大的内存地址,映射到很小的 CPU Cache 地址里。
70 |
71 | 要想写出让 CPU 跑得更快的代码,就需要写出缓存命中率高的代码,CPU L1 Cache 分为数据缓存和指令缓存,因而需要分别提高它们的缓存命中率:
72 |
73 | - 对于数据缓存,我们在遍历数据的时候,应该按照内存布局的顺序操作,这是因为 CPU Cache 是根据 CPU Cache Line 批量操作数据的,所以顺序地操作连续内存数据时,性能能得到有效的提升;
74 | - 对于指令缓存,有规律的条件分支语句能够让 CPU 的分支预测器发挥作用,进一步提高执行的效率;
75 |
76 | 另外,对于多核 CPU 系统,线程可能在不同 CPU 核心来回切换,这样各个核心的缓存命中率就会受到影响,于是要想提高线程的缓存命中率,可以考虑把线程绑定 CPU 到某一个 CPU 核心。
77 |
78 |
79 |
80 | ## 2.4 CPU 缓存一致性
81 |
82 |
83 |
84 | CPU 在读写数据的时候,都是在 CPU Cache 读写数据的,原因是 Cache 离 CPU 很近,读写性能相比内存高出很多。对于 Cache 里没有缓存 CPU 所需要读取的数据的这种情况,CPU 则会从内存读取数据,并将数据缓存到 Cache 里面,最后 CPU 再从 Cache 读取数据。
85 |
86 | 而对于数据的写入,CPU 都会先写入到 Cache 里面,然后再在找个合适的时机写入到内存,那就有「写直达」和「写回」这两种策略来保证 Cache 与内存的数据一致性:
87 |
88 | - 写直达,只要有数据写入,都会直接把数据写入到内存里面,这种方式简单直观,但是性能就会受限于内存的访问速度;
89 | - 写回,对于已经缓存在 Cache 的数据的写入,只需要更新其数据就可以,不用写入到内存,只有在需要把缓存里面的脏数据交换出去的时候,才把数据同步到内存里,这种方式在缓存命中率高的情况,性能会更好;
90 |
91 | 当今 CPU 都是多核的,每个核心都有各自独立的 L1/L2 Cache,只有 L3 Cache 是多个核心之间共享的。所以,我们要确保多核缓存是一致性的,否则会出现错误的结果。
92 |
93 | 要想实现缓存一致性,关键是要满足 2 点:
94 |
95 | - 第一点是写传播,也就是当某个 CPU 核心发生写入操作时,需要把该事件广播通知给其他核心;
96 | - 第二点是事物的串行化,这个很重要,只有保证了这个,才能保障我们的数据是真正一致的,我们的程序在各个不同的核心上运行的结果也是一致的;
97 |
98 | 基于总线嗅探机制的 MESI 协议,就满足上面了这两点,因此它是保障缓存一致性的协议。
99 |
100 | MESI 协议,是已修改、独占、共享、已失效这四个状态的英文缩写的组合。整个 MSI 状态的变更,则是根据来自本地 CPU 核心的请求,或者来自其他 CPU 核心通过总线传输过来的请求,从而构成一个流动的状态机。另外,对于在「已修改」或者「独占」状态的 Cache Line,修改更新其数据不需要发送广播给其他 CPU 核心。
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | ## 2.5 CPU 是如何执行任务的?
111 |
112 |
113 |
114 | 理解 CPU 是如何读写数据的前提,是要理解 CPU 的架构,CPU 内部的多个 Cache + 外部的内存和磁盘都就构成了金字塔的存储器结构,在这个金字塔中,越往下,存储器的容量就越大,但访问速度就会小。
115 |
116 | CPU 读写数据的时候,并不是按一个一个字节为单位来进行读写,而是以 CPU Line 大小为单位,CPU Line 大小一般是 64 个字节,也就意味着 CPU 读写数据的时候,每一次都是以 64 字节大小为一块进行操作。
117 |
118 | 因此,如果我们操作的数据是数组,那么访问数组元素的时候,按内存分布的地址顺序进行访问,这样能充分利用到 Cache,程序的性能得到提升。但如果操作的数据不是数组,而是普通的变量,并在多核 CPU 的情况下,我们还需要避免 Cache Line 伪共享的问题。
119 |
120 | 所谓的 Cache Line 伪共享问题就是,多个线程同时读写同一个 Cache Line 的不同变量时,而导致 CPU Cache 失效的现象。那么对于多个线程共享的热点数据,即经常会修改的数据,应该避免这些数据刚好在同一个 Cache Line 中,避免的方式一般有 Cache Line 大小字节对齐,以及字节填充等方法。
121 |
122 | 系统中需要运行的多线程数一般都会大于 CPU 核心,这样就会导致线程排队等待 CPU,这可能会产生一定的延时,如果我们的任务对延时容忍度很低,则可以通过一些人为手段干预 Linux 的默认调度策略和优先级。
123 |
124 |
125 |
126 | ## 2.6 什么是软中断?
127 |
128 | 为了避免由于中断处理程序执行时间过长,而影响正常进程的调度,Linux 将中断处理程序分为上半部和下半部:
129 |
130 | - 上半部,对应硬中断,由硬件触发中断,用来快速处理中断;
131 | - 下半部,对应软中断,由内核触发中断,用来异步处理上半部未完成的工作;
132 |
133 | Linux 中的软中断包括网络收发、定时、调度、RCU 锁等各种类型,可以通过查看 /proc/softirqs 来观察软中断的累计中断次数情况,如果要实时查看中断次数的变化率,可以使用 watch -d cat /proc/softirqs 命令。
134 |
135 | 每一个 CPU 都有各自的软中断内核线程,我们还可以用 ps 命令来查看内核线程,一般名字在中括号里面到,都认为是内核线程。
136 |
137 | 如果在 top 命令发现,CPU 在软中断上的使用率比较高,而且 CPU 使用率最高的进程也是软中断 ksoftirqd 的时候,这种一般可以认为系统的开销被软中断占据了。
138 |
139 | 这时我们就可以分析是哪种软中断类型导致的,一般来说都是因为网络接收软中断导致的,如果是的话,可以用 sar 命令查看是哪个网卡的有大量的网络包接收,再用 tcpdump 抓网络包,做进一步分析该网络包的源头是不是非法地址,如果是就需要考虑防火墙增加规则,如果不是,则考虑硬件升级等。
140 |
141 |
142 |
143 |
144 |
145 | ## 2.7 为什么 0.1 + 0.2 不等于 0.3 ?
146 |
147 | 最后,再来回答开头的问题。
148 |
149 | > 为什么负数要用补码表示?
150 |
151 | 负数之所以用补码的方式来表示,主要是为了统一和正数的加减法操作一样,毕竟数字的加减法是很常用的一个操作,就不要搞特殊化,尽量以统一的方式来运算。
152 |
153 | > 十进制小数怎么转成二进制?
154 |
155 | 十进制整数转二进制使用的是「除 2 取余法」,十进制小数使用的是「乘 2 取整法」。
156 |
157 | > 计算机是怎么存小数的?
158 |
159 | 计算机是以浮点数的形式存储小数的,大多数计算机都是 IEEE 754 标准定义的浮点数格式,包含三个部分:
160 |
161 | - 符号位:表示数字是正数还是负数,为 0 表示正数,为 1 表示负数;
162 | - 指数位:指定了小数点在数据中的位置,指数可以是负数,也可以是正数,指数位的长度越长则数值的表达范围就越大;
163 | - 尾数位:小数点右侧的数字,也就是小数部分,比如二进制 1.0011 x 2^(-2),尾数部分就是 0011,而且尾数的长度决定了这个数的精度,因此如果要表示精度更高的小数,则就要提高尾数位的长度;
164 |
165 | 用 32 位来表示的浮点数,则称为单精度浮点数,也就是我们编程语言中的 float 变量,而用 64 位来表示的浮点数,称为双精度浮点数,也就是 double 变量。
166 |
167 | > 0.1 + 0.2 == 0.3 吗?
168 |
169 | 不是的,0.1 和 0.2 这两个数字用二进制表达会是一个一直循环的二进制数,比如 0.1 的二进制表示为 0.0 0011 0011 0011… (0011 无限循环),对于计算机而言,0.1 无法精确表达,这是浮点数计算造成精度损失的根源。
170 |
171 | 因此,IEEE 754 标准定义的浮点数只能根据精度舍入,然后用「近似值」来表示该二进制,那么意味着计算机存放的小数可能不是一个真实值。
172 |
173 | 0.1 + 0.2 并不等于完整的 0.3,这主要是因为这两个小数无法用「完整」的二进制来表示,只能根据精度舍入,所以计算机里只能采用近似数的方式来保存,那两个近似数相加,得到的必然也是一个近似数。
174 |
175 |
176 |
177 | # 操作系统结构
178 |
179 | ## 3.1 Linux 内核 vs Windows 内核
180 |
181 |
182 |
183 | 对于内核的架构一般有这三种类型:
184 |
185 | - 宏内核,包含多个模块,整个内核像一个完整的程序;
186 | - 微内核,有一个最小版本的内核,一些模块和服务则由用户态管理;
187 | - 混合内核,是宏内核和微内核的结合体,内核中抽象出了微内核的概念,也就是内核中会有一个小型的内核,其他模块就在这个基础上搭建,整个内核是个完整的程序;
188 |
189 | Linux 的内核设计是采用了宏内核,Window 的内核设计则是采用了混合内核。
190 |
191 | 这两个操作系统的可执行文件格式也不一样, Linux 可执行文件格式叫作 ELF,Windows 可执行文件格式叫作 PE。
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 | # 内存管理
200 |
201 | ## 4.1 为什么要有虚拟内存?
202 |
203 | 为了在多进程环境下,使得进程之间的内存地址不受影响,相互隔离,于是操作系统就为每个进程独立分配一套**虚拟地址空间**,每个程序只关心自己的虚拟地址就可以,实际上大家的虚拟地址都是一样的,但分布到物理地址内存是不一样的。作为程序,也不用关心物理地址的事情。
204 |
205 | 每个进程都有自己的虚拟空间,而物理内存只有一个,所以当启用了大量的进程,物理内存必然会很紧张,于是操作系统会通过**内存交换**技术,把不常使用的内存暂时存放到硬盘(换出),在需要的时候再装载回物理内存(换入)。
206 |
207 | 那既然有了虚拟地址空间,那必然要把虚拟地址「映射」到物理地址,这个事情通常由操作系统来维护。
208 |
209 | 那么对于虚拟地址与物理地址的映射关系,可以有**分段**和**分页**的方式,同时两者结合都是可以的。
210 |
211 | 内存分段是根据程序的逻辑角度,分成了栈段、堆段、数据段、代码段等,这样可以分离出不同属性的段,同时是一块连续的空间。但是每个段的大小都不是统一的,这就会导致内存碎片和内存交换效率低的问题。
212 |
213 | 于是,就出现了内存分页,把虚拟空间和物理空间分成大小固定的页,如在 Linux 系统中,每一页的大小为 `4KB`。由于分了页后,就不会产生细小的内存碎片。同时在内存交换的时候,写入硬盘也就一个页或几个页,这就大大提高了内存交换的效率。
214 |
215 | 再来,为了解决简单分页产生的页表过大的问题,就有了**多级页表**,它解决了空间上的问题,但这就会导致 CPU 在寻址的过程中,需要有很多层表参与,加大了时间上的开销。于是根据程序的**局部性原理**,在 CPU 芯片中加入了 **TLB**,负责缓存最近常被访问的页表项,大大提高了地址的转换速度。
216 |
217 | **Linux 系统主要采用了分页管理,但是由于 Intel 处理器的发展史,Linux 系统无法避免分段管理**。于是 Linux 就把所有段的基地址设为 `0`,也就意味着所有程序的地址空间都是线性地址空间(虚拟地址),相当于屏蔽了 CPU 逻辑地址的概念,所以段只被用于访问控制和内存保护。
218 |
219 | 另外,Linux 系统中虚拟空间分布可分为**用户态**和**内核态**两部分,其中用户态的分布:代码段、全局变量、BSS、函数栈、堆内存、映射区。
220 |
221 |
222 |
223 | ## 4.2 malloc 是如何分配内存的?
224 |
225 | 无总结 知道下就行
226 |
227 |
228 |
229 |
230 |
231 | # 进程管理
232 |
233 | ## 5.1 进程、线程基础知识
234 |
235 |
236 |
237 | ## 5.2 进程间有哪些通信方式?
238 |
239 |
240 |
241 | 由于每个进程的用户空间都是独立的,不能相互访问,这时就需要借助内核空间来实现进程间通信,原因很简单,每个进程都是共享一个内核空间。
242 |
243 | Linux 内核提供了不少进程间通信的方式,其中最简单的方式就是管道,管道分为「匿名管道」和「命名管道」。
244 |
245 | **匿名管道**顾名思义,它没有名字标识,匿名管道是特殊文件只存在于内存,没有存在于文件系统中,shell 命令中的「`|`」竖线就是匿名管道,通信的数据是**无格式的流并且大小受限**,通信的方式是**单向**的,数据只能在一个方向上流动,如果要双向通信,需要创建两个管道,再来**匿名管道是只能用于存在父子关系的进程间通信**,匿名管道的生命周期随着进程创建而建立,随着进程终止而消失。
246 |
247 | **命名管道**突破了匿名管道只能在亲缘关系进程间的通信限制,因为使用命名管道的前提,需要在文件系统创建一个类型为 p 的设备文件,那么毫无关系的进程就可以通过这个设备文件进行通信。另外,不管是匿名管道还是命名管道,进程写入的数据都是**缓存在内核**中,另一个进程读取数据时候自然也是从内核中获取,同时通信数据都遵循**先进先出**原则,不支持 lseek 之类的文件定位操作。
248 |
249 | **消息队列**克服了管道通信的数据是无格式的字节流的问题,消息队列实际上是保存在内核的「消息链表」,消息队列的消息体是可以用户自定义的数据类型,发送数据时,会被分成一个一个独立的消息体,当然接收数据时,也要与发送方发送的消息体的数据类型保持一致,这样才能保证读取的数据是正确的。消息队列通信的速度不是最及时的,毕竟**每次数据的写入和读取都需要经过用户态与内核态之间的拷贝过程。**
250 |
251 | **共享内存**可以解决消息队列通信中用户态与内核态之间数据拷贝过程带来的开销,**它直接分配一个共享空间,每个进程都可以直接访问**,就像访问进程自己的空间一样快捷方便,不需要陷入内核态或者系统调用,大大提高了通信的速度,享有**最快**的进程间通信方式之名。但是便捷高效的共享内存通信,**带来新的问题,多进程竞争同个共享资源会造成数据的错乱。**
252 |
253 | 那么,就需要**信号量**来保护共享资源,以确保任何时刻只能有一个进程访问共享资源,这种方式就是互斥访问。**信号量不仅可以实现访问的互斥性,还可以实现进程间的同步**,信号量其实是一个计数器,表示的是资源个数,其值可以通过两个原子操作来控制,分别是 **P 操作和 V 操作**。
254 |
255 | 与信号量名字很相似的叫**信号**,它俩名字虽然相似,但功能一点儿都不一样。信号是**异步通信机制**,信号可以在应用进程和内核之间直接交互,内核也可以利用信号来通知用户空间的进程发生了哪些系统事件,信号事件的来源主要有硬件来源(如键盘 Cltr+C )和软件来源(如 kill 命令),一旦有信号发生,**进程有三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号**。有两个信号是应用进程无法捕捉和忽略的,即 `SIGKILL` 和 `SIGSTOP`,这是为了方便我们能在任何时候结束或停止某个进程。
256 |
257 | 前面说到的通信机制,都是工作于同一台主机,如果**要与不同主机的进程间通信,那么就需要 Socket 通信了**。Socket 实际上不仅用于不同的主机进程间通信,还可以用于本地主机进程间通信,可根据创建 Socket 的类型不同,分为三种常见的通信方式,一个是基于 TCP 协议的通信方式,一个是基于 UDP 协议的通信方式,一个是本地进程间通信方式。
258 |
259 | 以上,就是进程间通信的主要机制了。你可能会问了,那线程通信间的方式呢?
260 |
261 | 同个进程下的线程之间都是共享进程的资源,只要是共享变量都可以做到线程间通信,比如全局变量,所以对于线程间关注的不是通信方式,而是关注多线程竞争共享资源的问题,信号量也同样可以在线程间实现互斥与同步:
262 |
263 | - 互斥的方式,可保证任意时刻只有一个线程访问共享资源;
264 | - 同步的方式,可保证线程 A 应在线程 B 之前执行;
265 |
266 |
267 |
268 | ## 5.3 多线程冲突了怎么办?
269 |
270 |
271 |
272 | ## 5.4 怎么避免死锁?
273 |
274 | 简单来说,死锁问题的产生是由两个或者以上线程并行执行的时候,争夺资源而互相等待造成的。
275 |
276 | 死锁只有同时满足互斥、持有并等待、不可剥夺、环路等待这四个条件的时候才会发生。
277 |
278 | 所以要避免死锁问题,就是要破坏其中一个条件即可,最常用的方法就是使用资源有序分配法来破坏环路等待条件。
279 |
280 |
281 |
282 | ## 5.5 什么是悲观锁,乐观锁?
283 |
284 | 开发过程中,最常见的就是互斥锁的了,互斥锁加锁失败时,会用「线程切换」来应对,当加锁失败的线程再次加锁成功后的这一过程,会有两次线程上下文切换的成本,性能损耗比较大。
285 |
286 | 如果我们明确知道被锁住的代码的执行时间很短,那我们应该选择开销比较小的自旋锁,因为自旋锁加锁失败时,并不会主动产生线程切换,而是一直忙等待,直到获取到锁,那么如果被锁住的代码执行时间很短,那这个忙等待的时间相对应也很短。
287 |
288 | 如果能区分读操作和写操作的场景,那读写锁就更合适了,它允许多个读线程可以同时持有读锁,提高了读的并发性。根据偏袒读方还是写方,可以分为读优先锁和写优先锁,读优先锁并发性很强,但是写线程会被饿死,而写优先锁会优先服务写线程,读线程也可能会被饿死,那为了避免饥饿的问题,于是就有了公平读写锁,它是用队列把请求锁的线程排队,并保证先入先出的原则来对线程加锁,这样便保证了某种线程不会被饿死,通用性也更好点。
289 |
290 | 互斥锁和自旋锁都是最基本的锁,读写锁可以根据场景来选择这两种锁其中的一个进行实现。
291 |
292 | 另外,互斥锁、自旋锁、读写锁都**属于悲观锁**,悲观锁认为并发访问共享资源时,冲突概率可能非常高,所以在访问共享资源前,都需要先加锁。
293 |
294 | 相反的,如果并发访问共享资源时,冲突概率非常低的话,就可以使用乐观锁,它的工作方式是,在访问共享资源时,不用先加锁,修改完共享资源后,再验证这段时间内有没有发生冲突,如果没有其他线程在修改资源,那么操作完成,如果发现有其他线程已经修改过这个资源,就放弃本次操作。
295 |
296 | 但是,一旦冲突概率上升,就不适合使用乐观锁了,因为它解决冲突的重试成本非常高。
297 |
298 | 不管使用的哪种锁,我们的加锁的代码范围应该尽可能的小,也就是加锁的粒度要小,这样执行速度会比较快。再来,使用上了合适的锁,就会快上加快了。
299 |
300 |
301 |
302 | ## 5.6 一个进程最多可以创建多少个线程
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 | # 调度算法
311 |
312 | ## 6.1 进程调度/页面置换/磁盘调度算法
313 |
314 |
315 |
316 | # 文件系统
317 |
318 | ## 7.1 文件系统全家桶
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 | # 设备管理
327 |
328 | ## 8.1 键盘敲入 A 字母时,操作系统期间发生了什么?
329 |
330 |
331 |
332 | # 网络系统
333 |
334 | ## 9.1 什么是零拷贝?
335 |
336 | 早期 I/O 操作,内存与磁盘的数据传输的工作都是由 CPU 完成的,而此时 CPU 不能执行其他任务,会特别浪费 CPU 资源。
337 |
338 | 于是,为了解决这一问题,DMA 技术就出现了,每个 I/O 设备都有自己的 DMA 控制器,通过这个 DMA 控制器,CPU 只需要告诉 DMA 控制器,我们要传输什么数据,从哪里来,到哪里去,就可以放心离开了。后续的实际数据传输工作,都会由 DMA 控制器来完成,CPU 不需要参与数据传输的工作。
339 |
340 | 传统 IO 的工作方式,从硬盘读取数据,然后再通过网卡向外发送,我们需要进行 4 上下文切换,和 4 次数据拷贝,其中 2 次数据拷贝发生在内存里的缓冲区和对应的硬件设备之间,这个是由 DMA 完成,另外 2 次则发生在内核态和用户态之间,这个数据搬移工作是由 CPU 完成的。
341 |
342 | 为了提高文件传输的性能,于是就出现了零拷贝技术,它通过一次系统调用(`sendfile` 方法)合并了磁盘读取与网络发送两个操作,降低了上下文切换次数。另外,拷贝数据都是发生在内核中的,天然就降低了数据拷贝的次数。
343 |
344 | Kafka 和 Nginx 都有实现零拷贝技术,这将大大提高文件传输的性能。
345 |
346 | 零拷贝技术是基于 PageCache 的,PageCache 会缓存最近访问的数据,提升了访问缓存数据的性能,同时,为了解决机械硬盘寻址慢的问题,它还协助 I/O 调度算法实现了 IO 合并与预读,这也是顺序读比随机读性能好的原因。这些优势,进一步提升了零拷贝的性能。
347 |
348 | 需要注意的是,零拷贝技术是不允许进程对文件内容作进一步的加工的,比如压缩数据再发送。
349 |
350 | 另外,当传输大文件时,不能使用零拷贝,因为可能由于 PageCache 被大文件占据,而导致「热点」小文件无法利用到 PageCache,并且大文件的缓存命中率不高,这时就需要使用「异步 IO + 直接 IO 」的方式。
351 |
352 | 在 Nginx 里,可以通过配置,设定一个文件大小阈值,针对大文件使用异步 IO 和直接 IO,而对小文件使用零拷贝。
353 |
354 |
355 |
356 | ## 9.2 I/O 多路复用:select/poll/epoll
357 |
358 | 最基础的 TCP 的 Socket 编程,它是阻塞 I/O 模型,基本上只能一对一通信,那为了服务更多的客户端,我们需要改进网络 I/O 模型。
359 |
360 | 比较传统的方式是使用多进程/线程模型,每来一个客户端连接,就分配一个进程/线程,然后后续的读写都在对应的进程/线程,这种方式处理 100 个客户端没问题,但是当客户端增大到 10000 个时,10000 个进程/线程的调度、上下文切换以及它们占用的内存,都会成为瓶颈。
361 |
362 | 为了解决上面这个问题,就出现了 I/O 的多路复用,可以只在一个进程里处理多个文件的 I/O,Linux 下有三种提供 I/O 多路复用的 API,分别是: select、poll、epoll。
363 |
364 | select 和 poll 并没有本质区别,它们内部都是使用「线性结构」来存储进程关注的 Socket 集合。
365 |
366 | 在使用的时候,首先需要把关注的 Socket 集合通过 select/poll 系统调用从用户态拷贝到内核态,然后由内核检测事件,当有网络事件产生时,内核需要遍历进程关注 Socket 集合,找到对应的 Socket,并设置其状态为可读/可写,然后把整个 Socket 集合从内核态拷贝到用户态,用户态还要继续遍历整个 Socket 集合找到可读/可写的 Socket,然后对其处理。
367 |
368 | 很明显发现,select 和 poll 的缺陷在于,当客户端越多,也就是 Socket 集合越大,Socket 集合的遍历和拷贝会带来很大的开销,因此也很难应对 C10K。
369 |
370 | epoll 是解决 C10K 问题的利器,通过两个方面解决了 select/poll 的问题。
371 |
372 | - epoll 在内核里使用「红黑树」来关注进程所有待检测的 Socket,红黑树是个高效的数据结构,增删查一般时间复杂度是 O(logn),通过对这棵黑红树的管理,不需要像 select/poll 在每次操作时都传入整个 Socket 集合,减少了内核和用户空间大量的数据拷贝和内存分配。
373 | - epoll 使用事件驱动的机制,内核里维护了一个「链表」来记录就绪事件,只将有事件发生的 Socket 集合传递给应用程序,不需要像 select/poll 那样轮询扫描整个集合(包含有和无事件的 Socket ),大大提高了检测的效率。
374 |
375 | 而且,epoll 支持边缘触发和水平触发的方式,而 select/poll 只支持水平触发,一般而言,边缘触发的方式会比水平触发的效率高。
376 |
377 |
378 |
379 | ## 9.3 高性能网络模式:Reactor 和 Proactor
380 |
381 | 常见的 Reactor 实现方案有三种。
382 |
383 | 第一种方案单 Reactor 单进程 / 线程,不用考虑进程间通信以及数据同步的问题,因此实现起来比较简单,这种方案的缺陷在于无法充分利用多核 CPU,而且处理业务逻辑的时间不能太长,否则会延迟响应,所以不适用于计算机密集型的场景,适用于业务处理快速的场景,比如 Redis 采用的是单 Reactor 单进程的方案。
384 |
385 | 第二种方案单 Reactor 多线程,通过多线程的方式解决了方案一的缺陷,但它离高并发还差一点距离,差在只有一个 Reactor 对象来承担所有事件的监听和响应,而且只在主线程中运行,在面对瞬间高并发的场景时,容易成为性能的瓶颈的地方。
386 |
387 | 第三种方案多 Reactor 多进程 / 线程,通过多个 Reactor 来解决了方案二的缺陷,主 Reactor 只负责监听事件,响应事件的工作交给了从 Reactor,Netty 和 Memcache 都采用了「多 Reactor 多线程」的方案,Nginx 则采用了类似于 「多 Reactor 多进程」的方案。
388 |
389 | Reactor 可以理解为「来了事件操作系统通知应用进程,让应用进程来处理」,而 Proactor 可以理解为「来了事件操作系统来处理,处理完再通知应用进程」。
390 |
391 | 因此,真正的大杀器还是 Proactor,它是采用异步 I/O 实现的异步网络模型,感知的是已完成的读写事件,而不需要像 Reactor 感知到事件后,还需要调用 read 来从内核中获取数据。
392 |
393 | 不过,无论是 Reactor,还是 Proactor,都是一种基于「事件分发」的网络编程模式,区别在于 Reactor 模式是基于「待完成」的 I/O 事件,而 Proactor 模式则是基于「已完成」的 I/O 事件。
394 |
395 |
396 |
397 | ## 9.4 什么是一致性哈希?
398 |
399 | 不同的负载均衡算法适用的业务场景也不同的。
400 |
401 | 轮询这类的策略只能适用与每个节点的数据都是相同的场景,访问任意节点都能请求到数据。但是不适用分布式系统,因为分布式系统意味着数据水平切分到了不同的节点上,访问数据的时候,一定要寻址存储该数据的节点。
402 |
403 | 哈希算法虽然能建立数据和节点的映射关系,但是每次在节点数量发生变化的时候,最坏情况下所有数据都需要迁移,这样太麻烦了,所以不适用节点数量变化的场景。
404 |
405 | 为了减少迁移的数据量,就出现了一致性哈希算法。
406 |
407 | 一致性哈希是指将「存储节点」和「数据」都映射到一个首尾相连的哈希环上,如果增加或者移除一个节点,仅影响该节点在哈希环上顺时针相邻的后继节点,其它数据也不会受到影响。
408 |
409 | 但是一致性哈希算法不能够均匀的分布节点,会出现大量请求都集中在一个节点的情况,在这种情况下进行容灾与扩容时,容易出现雪崩的连锁反应。
410 |
411 | 为了解决一致性哈希算法不能够均匀的分布节点的问题,就需要引入虚拟节点,对一个真实节点做多个副本。不再将真实节点映射到哈希环上,而是将虚拟节点映射到哈希环上,并将虚拟节点映射到实际节点,所以这里有「两层」映射关系。
412 |
413 | 引入虚拟节点后,可以会提高节点的均衡度,还会提高系统的稳定性。所以,带虚拟节点的一致性哈希方法不仅适合硬件配置不同的节点的场景,而且适合节点规模会发生变化的场景。
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 | # 十、Linux命令
422 |
423 | ## 10.1 如何查看网络的性能指标?
424 |
425 |
426 |
427 |
428 |
429 | ## 10.2 如何从日志分析 PV、UV?
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 | # 自己记录的问题
462 |
463 | - L1 Cache 和 L2 Cache 都是每个 CPU 核心独有的,而 L3 Cache 是多个 CPU 核心共享的。这三个属于CPU Cache
464 |
465 | - 不连续性的话会导致缓存命中率不高,代码运行性能低,跳跃访问会比顺序访问效率低。
466 |
467 | - 缓存一致性。
468 |
469 | - 2.5的cpu调度是内核结构 6.1则是操作系统中。
470 |
471 | - 负数为什么用补码的方式表示,原因是在做基本加减法运算时,可以减少一步判断正负。
472 |
473 | - 二进制表示小数可能会出现精度丢失问题
474 |
475 | - ==宏内核==:简单来说,就是把很多东西都集成进内核,例如linux内核,除了最基本的进程、线程管理、内存管理外,文件系统,驱动,网络协议等等都在内核里面。
476 | 优点:效率高。
477 | 缺点:稳定性差,开发过程中的bug经常会导致整个系统挂掉。
478 | ==微内核==:内核中只有最基本的调度、内存管理。驱动、文件系统等都是用户态的守护进程去实现的。
479 | 优点:超级稳定,驱动等的错误只会导致相应进程死掉,不会导致整个系统都崩溃,做驱动开发时,发现错误,只需要kill掉进程,修正后重启进程就行了,比较方便。
480 | 缺点:效率低
481 |
482 | - 分段的好处就是能产生连续的内存空间,但是会出现内存碎片和内存交换的空间太大的问题。
483 |
484 | - 页表一定要覆盖全部虚拟地址空间,不分级的页表就需要有 100 多万个页表项来映射,而二级分页则只需要 1024 个页表项
485 |
486 | - 段页式虽然增加了硬件成本和系统开销,但是提高了内存利用率
487 |
488 | - 多级页表解决空间问题,TLB解决时间问题
489 |
490 | - 运行一个程序就叫一个进程
491 |
492 | - 进程实际上还有种挂起状态,就是不用了,将该进程的物理内存空间换出到硬盘,等需要再次运行的时候,再换回来,除了减少空间的占用,用sleep也可以使得进程挂起
493 |
494 | - **进程控制块**(*process control block,PCB*)是进程存在的唯一标识
495 |
496 | - 进程的状态什么的改变其实都是跟PCB有关的,修改对应的标识号,加入对应的队列或者移除出队列
497 |
498 | - CPU的上下文切换包括进程 线程 还有 中断上下文切换,把前一个任务的 CPU 上下文(CPU 寄存器和程序计数器)保存起来
499 |
500 | - 进程是由内核管理调度的,进程上下文切换的数据都是保存在PCB中的
501 |
502 | - 同一个进程内多个线程之间可以共享代码段、数据段、打开的文件等资源,但每个线程各自都有一套独立的寄存器和栈,这样可以确保线程的控制流是相对独立的。
503 |
504 | - IO所需CPU资源很少大部分都是给DMA的
505 |
506 | - **进程间通信**
507 |
508 | - 匿名管道的创建通过fork父进程的fd文件描述符,所以只能适用于父子进程,而命名管道有对应的管道文件,则可以适用于任意进程间,不相关也可,但都是遵循先进先出的原则
509 | - 消息队列比管道好的原因是,管道会一直等待被读,才释放,而消息队列放进去以后就可以正常返回了
510 |
511 | - 共享内存其实就是拿出一块虚拟地址空间,映射到相同的物理内存
512 | - 信号事件的来源主要有硬件来源(如键盘 Cltr+C )和软件来源(如 kill 命令)。 信号和信号量区分开来
513 | - 针对TCP协议的通信模型 connect要经历三次握手
514 |
515 | - 不同锁的成本,如果你能确定你被锁住的代码执行时间很短那就用自旋锁,不然上下文切换可能用的时间都比锁住的时间长,互斥锁会有两次上下文切换的消耗
516 |
517 | - 公平读写锁比较简单的一种方式是:用队列把获取锁的线程排队,不管是写线程还是读线程都按照先进先出的原则加锁即可,这样读线程仍然可以并发,也不会出现「饥饿」的现象
518 |
519 | - 在冲突概率小低、加锁成本高的场景下,才考虑使用乐观锁
520 |
521 | - 调度算法主要影响的是等待时间
522 |
523 | - 什么叫io繁忙型作业,就用一点cpu转而用io设备,这种就是短作业
524 |
525 | - 时间片轮转算法 缺点就是时间片太短会导致过多的上下文切换,如果时间片太长又可能会引起短作业响应时间过长
526 |
527 | - 磁盘到内存 算磁盘io
528 |
529 | - **页面置换的功能:当出现缺页异常,需调入新页面而内存已满时,选择被置换的物理页面,同时被置换出去的页面也得看下是否被修改过,倘若被修改过,还得将其写回磁盘**
530 |
531 | - 磁盘调度算法的目的很简单,就是为了提高磁盘的访问性能,一般是通过优化磁盘的访问请求顺序来做到的。就是最后性能好坏的评判,根据你访问距离来判断 **各个寻道算法都有相应的优缺点吧**
532 |
533 | - 文件系统的基本操作单元是数据块,用户读取的是字节
534 |
535 | - IO分为两个过程
536 | 1、数据准备的过程
537 | 2、数据从内核空间拷贝到用户进程缓冲区的过程
538 | 阻塞 I/O 会阻塞在「过程 1 」和「过程 2」,而非阻塞 I/O 和基于非阻塞 I/O 的多路复用只会阻塞在「过程 2」,所以这三个都可以认为是同步 I/O。
539 | 异步 I/O 则不同,「过程 1 」和「过程 2 」都不会阻塞。
540 |
541 | - IO 在频繁读写的状况下常用DMA
542 |
543 | - 针对磁盘的优化特别多比如零拷贝、直接I/O、异步I/O
544 |
545 | - 网络系统这章可以看出,为什么现在I/O只占用一点点CPU 通过DMA来
546 |
547 | - 要想提高文件传输的性能,就需要减少用户态和内核态的上下文切换和内核拷贝次数
548 |
549 | - 零拷贝就是提高文件传输性能 零拷贝技术实现的方式通常有2种
550 |
551 | - 1、mmap+write
552 | 这还不是最理想的状态,因为还是要通过CPU将缓存区的数据拷贝到socket缓存区中,仍然还需要4次上下文切换,因为系统调用还是2次
553 |
554 | 
555 |
556 | - 2、sendfile(linux内核版本必须2.1以上)
557 | 可以直接代替read() write() 只有两次上下文切换,三次数据拷贝 这个还是通过了CPU
558 |
559 | 
560 |
561 | linux 2.4版本之后进行了改变 直接不拷贝到socket缓存区了,虽然会将一些缓冲区描述符和数据长度传入socket缓存区 但也算减少了一次数据拷贝,这是真正的零拷贝
562 |
563 | 
564 |
565 | - 零拷贝技术的文件传输方式相比传统文件传输的方式,减少了 2 次上下文切换和数据拷贝次数,**只需要 2 次上下文切换和数据拷贝次数,就可以完成文件的传输,而且 2 次的数据拷贝过程,都不需要通过 CPU,2 次都是由 DMA 来搬运。**
566 |
567 | - Kafka使用到了零拷贝技术,它文件传输的代码最终调用了NIO库里的transferTo方法
568 |
569 | - 在拷贝的时候,用到了磁盘高速缓存(PageCache),优点:1、缓存最近被访问的数据2、预读功能。传大文件的时候就没什么用了
570 |
571 | - 大文件一般就是使用异步I/O+直接I/O,来替代零拷贝技术,直接IO绕过了pageCache
572 |
573 | - 关注关注socket模型(多进程、多线程、I/O多路复用)
574 |
575 | - 好好学Reactor这是Redis、Nginx、Netty等采用的方案
576 |
577 | - netty采用的就是多Reactor多线程的方案
578 | nginx采用的是多Reactor多进程的方案
579 |
580 | - **Reactor 是非阻塞同步网络模式,感知的是就绪可读写事件**。
581 | **Proactor 是异步网络模式, 感知的是已完成的读写事件**。 目前来说linux中的还不完善,同时socket也不支持
582 |
583 | - 应对分布式系统的算法一般采用一些一致性哈希算法等 这就是为了避免分布式系统在扩容 ,引入虚拟节点后,会提高节点的均衡度,还会提高系统的稳定性。
584 |
585 | - 应用程序要发送数据包时,通常是通过 socket 接口,于是就会发生系统调用,把应用层的数据拷贝到内核里的 socket 层,接着由网络协议栈从上到下逐层处理后,最后才会送到网卡发送出去。接收则相反。
586 |
587 | - PV Page Visitor UV Uniq Visitor
588 |
--------------------------------------------------------------------------------
/数据库查漏补缺.md:
--------------------------------------------------------------------------------
1 | # 数据库查漏补缺
2 |
3 | 1. DISTINCT必须直接放在列名前面,不能部分使用DISTINCT,一使用后面的全部奏效。
4 | 2. 我们写的 limit 3,4 换个方式是反着来的 limit 4 offset 3。
5 | 3. 指定一条ORDER BY子句时,应该保证它是SELECT语句中最后一条子句,如果不是则会出错,按多个列排序可以用逗号隔开,比如说 order by name,age 当name相同后,会根据age进行排序。
6 | 4. 排序 也存在按照列位置排序 就比如说 order by 1,2 就是根据1,2列的列名来排,不建议用这个方法进行排序,有可能出现问题。
7 | 5. 排序升序降序的关键字 ASC DESC 只应用到直接位于其前面的列名。
8 | 6. 如果将值与字符串类型的列进行比较,就需要限定引号。用来与数值列进行比较的值不用引号。
9 | 7. BETWEEN AND。
10 | 8. 通过过滤选择不包含指定值的所有行的时候,如果你希望返回含NULL值的行,但是这样做不到,NULL比较特殊所以在匹配过滤或非匹配过滤时不会返回这些结果。
11 | 9. 在Where后面的处理顺序 and会优先于or 所以像sql b=2 or a=1 and c<10 最好携程(b=2 or a=1)and c<10 圆括号具有更高的优先级。
12 | 10. NOT关键字从不单独使用,总是和其他操作符一起使用 在WHERE 子句中用来否定其后条件的关键字。
13 | 11. %可以匹配多个字符包括,0个字符。匹配不了NULL 。_可以匹配单个字符,[]集合通配符 sql yog不支持。 通配符搜索一般比其他搜索要耗费更多时间。
14 | 12. 将列拼接 mysql采用的是 concat(列名1,列名2)。
15 | 13. 虽然Select通常用于从表中检索数据,但是省略了from后面的子句就是简单地访问和处理表达式。比如说就是select 3*2 返回6 select curdate() 返回当前的日期等。
16 | 14. 有很多函数 典型的upper()转换成大写等。
17 | 15. 聚集函数的主要目标就是为了汇总出表的数据,而不查出数据本身。
18 | 16. COUNT(*)和COUNT(column)的区别,前者是对表中的行数目进行计数,不管表列中包含的是空值还是非空值,后者是对特定的列中具有值的行进行计数忽略空值。
19 | 17. WHERE在数据分组前过滤,HAVING在数组分组后进行过滤。
--------------------------------------------------------------------------------
/注解开发笔记.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzzzzzzzyt/JavaLearningNotes/d53263b10ab6655900423e19437efb3936f4a223/注解开发笔记.pdf
--------------------------------------------------------------------------------
/计算机网络查漏补缺.md:
--------------------------------------------------------------------------------
1 | # 计算机网络查漏补缺
2 |
3 |
4 |
5 | # 基础篇
6 |
7 | ## 2.1 TCP/IP 网络模型有哪几层?
8 |
9 | 综上所述,TCP/IP 网络通常是由上到下分成 4 层,分别是**应用层,传输层,网络层和网络接口层**。
10 |
11 | 
12 |
13 | 再给大家贴一下每一层的封装格式:
14 |
15 | 
16 |
17 | 网络接口层的传输单位是帧(frame),IP 层的传输单位是包(packet),TCP 层的传输单位是段(segment),HTTP 的传输单位则是消息或报文(message)。但这些名词并没有什么本质的区分,可以统称为数据包。
18 |
19 |
20 |
21 | ## 2.2 键入网址到网页显示,期间发生了什么?
22 |
23 |
24 |
25 |
26 |
27 | ## 2.3 Linux 系统是如何收发网络包的?
28 |
29 | 电脑与电脑之间通常都是通话网卡、交换机、路由器等网络设备连接到一起,那由于网络设备的异构性,国际标准化组织定义了一个七层的 OSI 网络模型,但是这个模型由于比较复杂,实际应用中并没有采用,而是采用了更为简化的 TCP/IP 模型,Linux 网络协议栈就是按照了该模型来实现的。
30 |
31 | TCP/IP 模型主要分为应用层、传输层、网络层、网络接口层四层,每一层负责的职责都不同,这也是 Linux 网络协议栈主要构成部分。
32 |
33 | 当应用程序通过 Socket 接口发送数据包,数据包会被网络协议栈从上到下进行逐层处理后,才会被送到网卡队列中,随后由网卡将网络包发送出去。
34 |
35 | 而在接收网络包时,同样也要先经过网络协议栈从下到上的逐层处理,最后才会被送到应用程序。
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | # HTTP篇
44 |
45 | ## 3.1 HTTP 常见面试题
46 |
47 |
48 |
49 | ## 3.2 HTTP/1.1如何优化?
50 |
51 | 这次主要从 3 个方面介绍了优化 HTTP/1.1 协议的思路。
52 |
53 | 第一个思路是,通过缓存技术来避免发送 HTTP 请求。客户端收到第一个请求的响应后,可以将其缓存在本地磁盘,下次请求的时候,如果缓存没过期,就直接读取本地缓存的响应数据。如果缓存过期,客户端发送请求的时候带上响应数据的摘要,服务器比对后发现资源没有变化,就发出不带包体的 304 响应,告诉客户端缓存的响应仍然有效。
54 |
55 | 第二个思路是,减少 HTTP 请求的次数,有以下的方法:
56 |
57 | 1. 将原本由客户端处理的重定向请求,交给代理服务器处理,这样可以减少重定向请求的次数;
58 | 2. 将多个小资源合并成一个大资源再传输,能够减少 HTTP 请求次数以及 头部的重复传输,再来减少 TCP 连接数量,进而省去 TCP 握手和慢启动的网络消耗;
59 | 3. 按需访问资源,只访问当前用户看得到/用得到的资源,当客户往下滑动,再访问接下来的资源,以此达到延迟请求,也就减少了同一时间的 HTTP 请求次数。
60 |
61 | 第三思路是,通过压缩响应资源,降低传输资源的大小,从而提高传输效率,所以应当选择更优秀的压缩算法。
62 |
63 | 不管怎么优化 HTTP/1.1 协议都是有限的,不然也不会出现 HTTP/2 和 HTTP/3 协议,后续我们再来介绍 HTTP/2 和 HTTP/3 协议
64 |
65 |
66 |
67 | ## 3.3 HTTPS RSA 握手解析
68 |
69 |
70 |
71 | ## 3.4 HTTPS ECDHE 握手解析
72 |
73 | RSA 和 ECDHE 握手过程的区别:
74 |
75 | - RSA 密钥协商算法「不支持」前向保密,ECDHE 密钥协商算法「支持」前向保密;
76 | - 使用了 RSA 密钥协商算法,TLS 完成四次握手后,才能进行应用数据传输,而对于 ECDHE 算法,客户端可以不用等服务端的最后一次 TLS 握手,就可以提前发出加密的 HTTP 数据,节省了一个消息的往返时间;
77 | - 使用 ECDHE, 在 TLS 第 2 次握手中,会出现服务器端发出的「Server Key Exchange」消息,而 RSA 握手过程没有该消息;
78 |
79 |
80 |
81 | ## 3.5 HTTPS 如何优化?
82 |
83 | 对于硬件优化的方向,因为 HTTPS 是属于计算密集型,应该选择计算力更强的 CPU,而且最好选择**支持 AES-NI 特性的 CPU**,这个特性可以在硬件级别优化 AES 对称加密算法,加快应用数据的加解密。
84 |
85 | 对于软件优化的方向,如果可以,把软件升级成较新的版本,比如将 Linux 内核 2.X 升级成 4.X,将 openssl 1.0.1 升级到 1.1.1,因为新版本的软件不仅会提供新的特性,而且还会修复老版本的问题。
86 |
87 | 对于协议优化的方向:
88 |
89 | - 密钥交换算法应该选择 **ECDHE 算法**,而不用 RSA 算法,因为 ECDHE 算法具备前向安全性,而且客户端可以在第三次握手之后,就发送加密应用数据,节省了 1 RTT。
90 | - 将 TSL1.2 升级 **TSL1.3**,因为 TSL1.3 的握手过程只需要 1 RTT,而且安全性更强。
91 |
92 | 对于证书优化的方向:
93 |
94 | - 服务器应该选用 **ECDSA 证书**,而非 RSA 证书,因为在相同安全级别下,ECC 的密钥长度比 RSA 短很多,这样可以提高证书传输的效率;
95 | - 服务器应该开启 **OCSP Stapling** 功能,由服务器预先获得 OCSP 的响应,并把响应结果缓存起来,这样 TLS 握手的时候就不用再访问 CA 服务器,减少了网络通信的开销,提高了证书验证的效率;
96 |
97 | 对于重连 HTTPS 时,我们可以使用一些技术让客户端和服务端使用上一次 HTTPS 连接使用的会话密钥,直接恢复会话,而不用再重新走完整的 TLS 握手过程。
98 |
99 | 常见的**会话重用**技术有 Session ID 和 Session Ticket,用了会话重用技术,当再次重连 HTTPS 时,只需要 1 RTT 就可以恢复会话。对于 TLS1.3 使用 Pre-shared Key 会话重用技术,只需要 0 RTT 就可以恢复会话。
100 |
101 | 这些会话重用技术虽然好用,但是存在一定的安全风险,它们不仅不具备前向安全,而且有重放攻击的风险,所以应当对会话密钥设定一个合理的过期时间。
102 |
103 | ## 3.6 HTTP/2 牛逼在哪?
104 |
105 | HTTP/2 协议其实还有很多内容,比如流控制、流状态、依赖关系等等。
106 |
107 | 这次主要介绍了关于 HTTP/2 是如何提示性能的几个方向,它相比 HTTP/1 大大提高了传输效率、吞吐能力。
108 |
109 | 第一点,对于常见的 HTTP 头部通过**静态表和 Huffman 编码**的方式,将体积压缩了近一半,而且针对后续的请求头部,还可以建立**动态表**,将体积压缩近 90%,大大提高了编码效率,同时节约了带宽资源。
110 |
111 | 不过,动态表并非可以无限增大, 因为动态表是会占用内存的,动态表越大,内存也越大,容易影响服务器总体的并发能力,因此服务器需要限制 HTTP/2 连接时长或者请求次数。
112 |
113 | 第二点,**HTTP/2 实现了 Stream 并发**,多个 Stream 只需复用 1 个 TCP 连接,节约了 TCP 和 TLS 握手时间,以及减少了 TCP 慢启动阶段对流量的影响。不同的 Stream ID 才可以并发,即时乱序发送帧也没问题,但是同一个 Stream 里的帧必须严格有序。
114 |
115 | 另外,可以根据资源的渲染顺序来设置 Stream 的**优先级**,从而提高用户体验。
116 |
117 | 第三点,**服务器支持主动推送资源**,大大提升了消息的传输性能,服务器推送资源时,会先发送 PUSH_PROMISE 帧,告诉客户端接下来在哪个 Stream 发送资源,然后用偶数号 Stream 发送资源给客户端。
118 |
119 | HTTP/2 通过 Stream 的并发能力,解决了 HTTP/1 队头阻塞的问题,看似很完美了,但是 HTTP/2 还是存在“队头阻塞”的问题,只不过问题不是在 HTTP 这一层面,而是在 TCP 这一层。
120 |
121 | **HTTP/2 是基于 TCP 协议来传输数据的,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用,那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据,这就是 HTTP/2 队头阻塞问题。**
122 |
123 | 有没有什么解决方案呢?既然是 TCP 协议自身的问题,那干脆放弃 TCP 协议,转而使用 UDP 协议作为传输层协议,这个大胆的决定, HTTP/3 协议做了!
124 |
125 | ## 3.7 HTTP/3 强势来袭
126 |
127 | HTTP/2 虽然具有多个流并发传输的能力,但是传输层是 TCP 协议,于是存在以下缺陷:
128 |
129 | - **队头阻塞**,HTTP/2 多个请求跑在一个 TCP 连接中,如果序列号较低的 TCP 段在网络传输中丢失了,即使序列号较高的 TCP 段已经被接收了,应用层也无法从内核中读取到这部分数据,从 HTTP 视角看,就是多个请求被阻塞了;
130 | - **TCP 和 TLS 握手时延**,TCL 三次握手和 TLS 四次握手,共有 3-RTT 的时延;
131 | - **连接迁移需要重新连接**,移动设备从 4G 网络环境切换到 WIFI 时,由于 TCP 是基于四元组来确认一条 TCP 连接的,那么网络环境变化后,就会导致 IP 地址或端口变化,于是 TCP 只能断开连接,然后再重新建立连接,切换网络环境的成本高;
132 |
133 | HTTP/3 就将传输层从 TCP 替换成了 UDP,并在 UDP 协议上开发了 QUIC 协议,来保证数据的可靠传输。
134 |
135 | QUIC 协议的特点:
136 |
137 | - **无队头阻塞**,QUIC 连接上的多个 Stream 之间并没有依赖,都是独立的,也不会有底层协议限制,某个流发生丢包了,只会影响该流,其他流不受影响;
138 | - **建立连接速度快**,因为 QUIC 内部包含 TLS1.3,因此仅需 1 个 RTT 就可以「同时」完成建立连接与 TLS 密钥协商,甚至在第二次连接的时候,应用数据包可以和 QUIC 握手信息(连接信息 + TLS 信息)一起发送,达到 0-RTT 的效果。
139 | - **连接迁移**,QUIC 协议没有用四元组的方式来“绑定”连接,而是通过「连接 ID 」来标记通信的两个端点,客户端和服务器可以各自选择一组 ID 来标记自己,因此即使移动设备的网络变化后,导致 IP 地址变化了,只要仍保有上下文信息(比如连接 ID、TLS 密钥等),就可以“无缝”地复用原连接,消除重连的成本;
140 |
141 | 另外 HTTP/3 的 QPACK 通过两个特殊的单向流来同步双方的动态表,解决了 HTTP/2 的 HPACK 队头阻塞问题。
142 |
143 |
144 |
145 | # TCP篇
146 |
147 | ## 4.1 TCP 三次握手与四次挥手面试题
148 |
149 | **小结**
150 |
151 | **TCP 建立连接时,通过三次握手**能防止历史连接的建立,能减少双方不必要的资源开销,能帮助双方同步初始化序列号**。序列号能够保证数据包不重复、不丢弃和按序传输。
152 |
153 | 不使用「两次握手」和「四次握手」的原因:
154 |
155 | - 「两次握手」:无法防止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号;
156 | - 「四次握手」:三次握手就已经理论上最少可靠连接建立,所以不需要使用更多的通信次数。
157 |
158 |
159 |
160 | ## 4.2 TCP 重传、滑动窗口、流量控制、拥塞控制
161 |
162 |
163 |
164 | ## 4.3 TCP 实战抓包分析
165 |
166 |
167 |
168 | ## 4.4 TCP 半连接队列和全连接队列
169 |
170 |
171 |
172 | ## 4.5 如何优化 TCP?
173 |
174 | [](https://imgtu.com/i/Oh7mY6)
175 |
176 | [](https://imgtu.com/i/Oh7ttP)
177 |
178 |
179 |
180 | [](https://imgtu.com/i/Ohj0PA)
181 |
182 | [](https://imgtu.com/i/OhjAg0)
183 |
184 |
185 |
186 | [](https://imgtu.com/i/OhjIx0)
187 |
188 |
189 |
190 | ## 4.6 如何理解是 TCP 面向字节流协议?
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 | ## 4.7 为什么 TCP 每次建立连接时,初始化序列号都要不一样呢?
199 |
200 |
201 |
202 | ## 4.8 SYN 报文什么时候情况下会被丢弃?
203 |
204 | 1、开启了一个设置 然后因为网络原因收到的数据包时间戳不是递增的就丢弃了
205 |
206 | 2、accept满了,半连接或者全连接
207 |
208 |
209 |
210 | ## 4.9 已建立连接的TCP,收到SYN会发生什么?
211 |
212 | 根据你客户端syn报文中的源端口有关,如果源端口是不一致的话,则重新建立连接,如一致的话,看源码也是会断开相应连接
213 |
214 |
215 |
216 | **如何关闭一个TCP连接**伪造RST报文 这样就可以让它们释放连接了
217 |
218 |
219 |
220 | ## 4.10 四次挥手中收到乱序的 FIN 包会如何处理?
221 |
222 | **在 FIN_WAIT_2 状态时,如果收到乱序的 FIN 报文,那么就被会加入到「乱序队列」,并不会进入到 TIME_WAIT 状态。**
223 |
224 | **等再次收到前面被网络延迟的数据包时,会判断乱序队列有没有数据,然后会检测乱序队列中是否有可用的数据,如果能在乱序队列中找到与当前报文的序列号保持的顺序的报文,就会看该报文是否有 FIN 标志,如果发现有 FIN 标志,这时才会进入 TIME_WAIT 状态。**
225 |
226 |
227 |
228 | ## 4.11 在 TIME_WAIT 状态的 TCP 连接,收到 SYN 后会发生什么?
229 |
230 | 在 TCP 正常挥手过程中,处于 TIME_WAIT 状态的连接,收到相同四元组的 SYN 后会发生什么?
231 |
232 | 如果双方开启了时间戳机制:
233 |
234 | - 如果客户端的 SYN 的「序列号」比服务端「期望下一个收到的序列号」要**大**,**并且**SYN 的「时间戳」比服务端「最后收到的报文的时间戳」要**大**。那么就会重用该四元组连接,跳过 2MSL 而转变为 SYN_RECV 状态,接着就能进行建立连接过程。
235 | - 如果客户端的 SYN 的「序列号」比服务端「期望下一个收到的序列号」要**小**,**或者**SYN 的「时间戳」比服务端「最后收到的报文的时间戳」要**小**。那么就会**再回复一个第四次挥手的 ACK 报文,客户端收到后,发现并不是自己期望收到确认号,就回 RST 报文给服务端**。
236 |
237 | 在 TIME_WAIT 状态,收到 RST 会断开连接吗?
238 |
239 | - 如果 `net.ipv4.tcp_rfc1337` 参数为 0,则提前结束 TIME_WAIT 状态,释放连接。
240 | - 如果 `net.ipv4.tcp_rfc1337` 参数为 1,则会丢掉该 RST 报文。
241 |
242 |
243 |
244 | ## 4.12 TCP 连接,一端断电和进程崩溃有什么区别?
245 |
246 | **在没有有开启去keep-alive且无数据传输的情况下**
247 |
248 | 断电的话服务端的TCP连接将会一直处于已建立连接状态
249 |
250 | 进程崩溃的话 会发送fin进行挥手 是可以感知到的
251 |
252 |
253 |
254 | **有数据传输情况下的问题**
255 |
256 | **客户端主机宕机又迅速重启**-只要有一方重启完成后收到之前的TCP连接的报文都会回复RST报文,以断开连接
257 |
258 | **客户端主机宕机,一直没有重启**,会重传,先到达最大重传次数或者最大超时时间其中一个条件后,就会停止重传
259 |
260 |
261 |
262 | ## 4.13 拔掉网线后, 原本的 TCP 连接还存在吗?
263 |
264 | 客户端拔掉网线后,并不会直接影响 TCP 连接状态。所以,拔掉网线后,TCP 连接是否还会存在,关键要看拔掉网线之后,有没有进行数据传输。
265 |
266 | 有数据传输的情况:
267 |
268 | - 在客户端拔掉网线后,如果服务端发送了数据报文,那么在服务端重传次数没有达到最大值之前,客户端就插回了网线,那么双方原本的 TCP 连接还是能正常存在,就好像什么事情都没有发生。
269 | - 在客户端拔掉网线后,如果服务端发送了数据报文,在客户端插回网线之前,服务端重传次数达到了最大值时,服务端就会断开 TCP 连接。等到客户端插回网线后,向服务端发送了数据,因为服务端已经断开了与客户端相同四元组的 TCP 连接,所以就会回 RST 报文,客户端收到后就会断开 TCP 连接。至此, 双方的 TCP 连接都断开了。
270 |
271 | 没有数据传输的情况:
272 |
273 | - 如果双方都没有开启 TCP keepalive 机制,那么在客户端拔掉网线后,如果客户端一直不插回网线,那么客户端和服务端的 TCP 连接状态将会一直保持存在。
274 | - 如果双方都开启了 TCP keepalive 机制,那么在客户端拔掉网线后,如果客户端一直不插回网线,TCP keepalive 机制会探测到对方的 TCP 连接没有存活,于是就会断开 TCP 连接。而如果在 TCP 探测期间,客户端插回了网线,那么双方原本的 TCP 连接还是能正常存在。
275 |
276 | 除了客户端拔掉网线的场景,还有客户端「宕机和进程崩解」的两种场景。
277 |
278 | 第一个场景,客户端宕机这件事跟拔掉网线是一样无法被服务端的感知的,所以如果在没有数据传输,并且没有开启 TCP keepalive 机制时,,**服务端的 TCP 连接将会一直处于 ESTABLISHED 连接状态**,直到服务端重启进程。
279 |
280 | 所以,我们可以得知一个点。在没有使用 TCP 保活机制,且双方不传输数据的情况下,一方的 TCP 连接处在 ESTABLISHED 状态时,并不代表另一方的 TCP 连接还一定是正常的。
281 |
282 | 第二个场景,客户端的进程崩解后,客户端的内核就会向服务端发送 FIN 报文,**与服务端进行四次挥手**。
283 |
284 | 所以,即使没有开启 TCP keepalive,且双方也没有数据交互的情况下,如果其中一方的进程发生了崩溃,这个过程操作系统是可以感知的到的,于是就会发送 FIN 报文给对方,然后与对方进行 TCP 四次挥手。
285 |
286 |
287 |
288 | ## 4.14 tcp_tw_reuse 为什么默认是关闭的?
289 |
290 | tcp_tw_reuse 的作用是让客户端快速复用处于 TIME_WAIT 状态的端口,相当于跳过了 TIME_WAIT 状态,这可能会出现这样的两个问题:
291 |
292 | - 历史 RST 报文可能会终止后面相同四元组的连接,因为 PAWS(防止序列号回绕) 检查到即使 RST 是过期的,也不会丢弃。
293 | - 如果第四次挥手的 ACK 报文丢失了,有可能被动关闭连接的一方不能被正常的关闭;
294 |
295 | 虽然 TIME_WAIT 状态持续的时间是有一点长,显得很不友好,但是它被设计来就是用来避免发生乱七八糟的事情。
296 |
297 |
298 |
299 | ## 4.15 HTTPS 中 TLS 和 TCP 能同时握手吗?
300 |
301 | 「HTTPS 是先进行 TCP 三次握手,再进行 TLSv1.2 四次握手」,这句话一点问题都没有,怀疑这句话是错的人,才有问题。
302 |
303 | 「HTTPS 中的 TLS 握手过程可以同时进行三次握手」,这个场景是可能存在到,但是在没有说任何前提条件,而说这句话就等于耍流氓。需要下面这两个条件同时满足才可以:
304 |
305 | - **客户端和服务端都开启了 TCP Fast Open 功能,且 TLS 版本是 1.3;**
306 | - **客户端和服务端已经完成过一次通信;**
307 |
308 |
309 |
310 | ## 4.16 TCP Keepalive 和 HTTP Keep-Alive 是一个东西吗?
311 |
312 | HTTP 的 Keep-Alive 也叫 HTTP 长连接,该功能是由「应用程序」实现的,可以使得用同一个 TCP 连接来发送和接收多个 HTTP 请求/应答,减少了 HTTP 短连接带来的多次 TCP 连接建立和释放的开销。
313 |
314 | TCP 的 Keepalive 也叫 TCP 保活机制,该功能是由「内核」实现的,当客户端和服务端长达一定时间没有进行数据交互时,内核为了确保该连接是否还有效,就会发送探测报文,来检测对方是否还在线,然后来决定是否要关闭该连接。
315 |
316 |
317 |
318 | ## 4.17 TCP 协议有什么缺陷?
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 | # IP篇
329 |
330 |
331 |
332 |
333 |
334 | ## 5.1 IP 基础知识全家桶
335 |
336 |
337 |
338 | ## 5.2 ping 的工作原理
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 | # 自己记录的问题
363 |
364 | - TCP/IP网络模型属于网络通信的一套通用的网络协议
365 |
366 | - 应用层是工作在操作系统的用户态,传输层及以下则工作在内核态
367 |
368 | - MSS(TCP最大报文段长度)
369 |
370 | - 传输层的报文会携带端口号的,因此接收方可以识别出该报文是发送给哪个应用
371 |
372 | - 网络层最常使用的是 IP 协议(*Internet Protocol*),IP 协议会将传输层的报文作为数据部分,再加上 IP 包头组装成 IP 报文,如果 IP 报文大小超过 MTU(以太网中一般为 1500 字节)就会**再次进行分片**,得到一个即将发送到网络的 IP 报文。
373 |
374 | - IP地址主要分成两种意义,一个是网络号,一个是主机号,根据掩码可以获取两者
375 |
376 | - **IP 协议的寻址作用是告诉我们去往下一个目的地==该朝哪个方向走==,路由则是==根据「下一个目的地」选择路径==。寻址更像在导航,路由更像在操作方向盘**。`自己用通俗的话讲一遍就是这个ip告诉我们最终要去哪个网络的哪台主机,路由的话就是咋去,遇到个路由器给他看,他帮你分配`
377 |
378 | - 网络接口层会将网络层的数据封装成帧,根据mac头部进行转发
379 |
380 | - ⭐其实我们访问对应的网址后面一系列的东西,其实最后都是请求他实际的域名的 比如`https://www.baidu.com/s?wd=杭州电子科技大学&rsv_spt=1&rsv_iqid=0xc992c3e7004b9c01&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8` 类似于这一段其实就是请求百度,后面是数据源的数据名,用来生成相应的请求报文发送给服务器域名进行请求
381 |
382 | - 必须用到DNS因为委托操作系统发送消息的时候,必须提供通信对象的IP地址(浏览器中会有域名的缓存,每次都会先看是否有缓存,再去请求DNS)
383 |
384 | - `MTU`:一个网络包的最大长度,以太网中一般为 `1500` 字节。
385 | `MSS`:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度。
386 |
387 | - TCP报文的源端口随机生成,目的端口根据你的请求,如果是HTTP请求那就是80 如果是其他就是其他规定的端口
388 |
389 | - TCP可靠传输 可以看看他的报文头部
390 |
391 | - 搞清楚 包发给谁 查一下路由表,根据路由表获得的ip然后使用arp协议找到对应路由器的mac地址,操作系统也会有arp缓存 不是每次都要广播获取
392 |
393 | - 在网络包传输的过程中,**源 IP 和目标 IP 始终是不会变的,一直变化的是 MAC 地址**,因为需要 MAC 地址在以太网内进行**两个设备**之间的包传输。
394 |
395 | - **HTTP 是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」。**
396 |
397 | - GET 的语义是请求获取指定的资源。GET 方法是安全、幂等、可被缓存的。
398 |
399 | POST 的语义是根据请求负荷(报文主体)对指定的资源做出处理,具体的处理方式视资源类型而不同。POST 不安全,不幂等,(大部分实现)不可缓存。
400 | (但不完全是这样 可以用get实现新增和删除那就不是安全和幂等了,用post实现查询,那就是安全和幂等)
401 |
402 | - GET请求其实也是可以带上body的同时POST请求的URL中也可以有参数
403 |
404 | - HTTP(1.1)优缺点一体的**双刃剑**,分别是「无状态、明文传输」,同时还有一大缺点「不安全」。
405 |
406 | - HTTP(1.1)性能 1、长连接 2、管道网络传输 3、响应队头阻塞
407 |
408 | - SSL/TLS 协议基本流程:
409 |
410 | - 客户端向服务器索要并验证服务器的公钥。
411 | - 双方协商生产「会话秘钥」。
412 | - 双方采用「会话秘钥」进行加密通信。
413 |
414 | - HTTP/1.1 相比 HTTP/1.0 性能上的改进:
415 |
416 | - 使用 TCP 长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。
417 | - 支持管道(pipeline)网络传输,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。
418 |
419 | - HTTP/1.1 还是有性能瓶颈:
420 |
421 | - 请求 / 响应头部(Header)未经压缩就发送,首部信息越多延迟越大。只能压缩 `Body` 的部分;
422 | - 发送冗长的首部。每次互相发送相同的首部造成的浪费较多;
423 | - 服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是队头阻塞;
424 | - 没有请求优先级控制;
425 | - 请求只能从客户端开始,服务器只能被动响应。
426 |
427 | - HTTP/2 相比 HTTP/1.1 性能上的改进:1、头部压缩 2、二进制格式 (原来传200 用三个字符转成二进制 24位 现在200直接一个8位的就解决掉了)3、数据流 4、多路复用 5、服务器推送
428 |
429 | - HTTP/2缺陷 还是存在队头阻塞问题 **HTTP/2 是基于 TCP 协议来传输数据的,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用,那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据,这就是 HTTP/2 队头阻塞问题。**
430 | 
431 |
432 | - HTTP/3 优化:使用了QUIC+UDP QUIC可以实现类似TCP的可靠传输 有以下特点1、无队头阻塞 2、更快的连接建立 3、连接迁移
433 |
434 | - HTTPS常用的密钥交换算法有两种,分别是RSA和ECDHE算法
435 |
436 | - rsa整个加密过程已经过的很舒服了,比起第一次看,这次看真的懂了很多(rsa没有前向安全性 参考下面)
437 |
438 | - 【前向安全性】:前向安全性或前向保密性(英语:Forward Secrecy,缩写:FS),有时也被称为完美前向安全(英语:Perfect Forward Secrecy,缩写:PFS),是密码学中通讯协议的安全属性,指的是长期使用的主密钥泄漏不会导致过去的会话密钥泄漏。
439 |
440 | - HTTPS的优化 硬件优化 软件优化 会话复用 协议优化 证书优化
441 |
442 | - 两次握手,无法避免历史连接
443 | 三次握手同步双方初始序列号
444 |
445 | - 如果单纯知识ip进行分片的话,是没有效率的,所以要有tcp分片
446 |
447 | - 第一次握手丢失 客户端触发超时重传
448 | 第二次握手丢失 服务端、客户端触发超时重传
449 | 第三次握手丢失 服务端超时重传
450 |
451 | - 三次握手成功后才是真正的应用 才是进行socket连接 就是accept
452 |
453 | - 第一次挥手丢失了 客户端会进行重传,超过重传的次数还没得到应答的后,会直接进行close状态
454 |
455 | - 不管有没有收到第二次挥手,客户端到后面都会处于fin_wait2状态
456 |
457 | - 内核是没有权利替代进程关闭连接,所以必须由进程主动调用close函数来触发服务端发送Fin
458 |
459 | - **MSL报文最大生存时间,MSL要大于TTL(IP数据包可以经过的最大路由数)消耗为0的时间,以确保报文已被自然消亡**
460 |
461 | - 主动发起连接的一方,才会有TIME-WAIT状态,需要这状态的两个原因,1、防止历史连接中的数据被后面相同四元组的错误接收 2、保证被动连接的一方能被正确关闭
462 |
463 | - socket tcp 客户端connect成功返回在第二次握手 服务端accept成功返回在第三次握手
464 |
465 | - RTT是数据发送时刻到接收到确认的时刻的差值(经常动态变化的值)
466 | RTO是超时重传时间 应该是略大于RTT不能太长也不能太短(也会是经常动态变化)
467 |
468 | - 快速重传机制,它不以时间为驱动,而是以数据驱动重传 其中还有两个其他实现重传的机制 SACK D-SACK
469 |
470 | - 接收窗口和发送窗口大小并不是完全相等的,因为传输过程是存在时延的,所以接收窗口和发送窗口是约等于关系
471 |
472 | - 糊涂窗口综合症 一点小数据也发 甚至还比不上TCP+的头要解决糊涂窗口综合症,就解决上面两个问题就可以了
473 |
474 | - 让接收方不通告小窗口给发送方(解决方法:当窗口小于min(MSS,缓存空间/2)就像发送方通告窗口大小为0)
475 | - 让发送方避免发送小数据(解决方法:Nagle算法 满足以下两个条件之一才可以发送数据:要等到窗口大小 >= MSS 或是数据大小>= MSS/////或者收到之前发送数据的ack回包)
476 |
477 | - 流量控制只是端到端的 拥塞控制很明显是应对整个网络中的环境
478 |
479 | - swnd = min(cwnd, rwnd) 发送窗口为拥塞窗口和接收窗口的小值,`我之前想的有点偏差,之前看那个拥塞窗口一直变大,觉得会传很多,原来是拥塞和发送窗口的小值,这下明白了所以说还是要多想想`
480 |
481 | - 拥塞窗口每收到一个ack+1,当超过慢启动门限后每超过一个窗口确认加1/cwnd,所以慢启动门限后所有的拥塞窗口都收到了 才+1
482 |
483 | - TCP解决粘包有三种方式:固定长度的消息;特殊字符作为边界(如果消息内部出现这个特殊字符的时候 需要对这个字符进行转义);自定义消息结构
484 |
485 | - 只有主动关闭的才有time_wait状态
486 |
487 | - MSL是由网络层的IP包中的TTL来保证的,TTL是IP头部的一个字段,用于设置一个数据报可经过的路由器数量上限
488 |
489 | - 设置time_wait的两大原因一定是要清楚
490 |
491 | - TCP第三次握手是可以携带数据的
492 |
493 | - TCP三次握手之后才能进行TLS1.2四次握手
494 |
495 | - 开启了TCP Fast Open之后 接收到客户端的请求,同时验证了cookie后响应ack 可立刻传输数据
496 |
497 | - HTTP的Keep-Alive是长连接
498 | TCP的Keep-Alive是TCP保活机制
499 |
500 | - 传输层是针对进程间的传输
501 | 网络层是针对主机间的传输
502 |
503 | - 数据链路层其实就是在没有直连之间的网络间中各个设备间的传输
504 |
505 | - IP地址中有两个IP是特殊的,分别是主机号全为1和全为0地址 全为1就是广播地址 全为0就是指定对应的网络
506 |
507 | - 有直接广播和本地广播 要知道是什么意思
508 |
509 | - ip分类其实就是能很快的判断分类 很快的找出网络地址和主机地址
510 |
511 | - 对某类地址可以再进行子网划分
512 |
513 | - 公有ip地址和私有ip地址 我们用的基本都是私有ip
514 |
515 | - DNS 有查询缓存的过程
516 |
517 | - ARP协议也是有查询缓存的过程,同时,但是换船是一定期限的,超过期限会删除 ARP会动态执行
518 |
519 | - **DHCP动态获取IP地址** 动态的请求服务器 获取相应的地址 也类似于有四次握手 用UDP广播通信 因为有路由器转发请求 所以不在一个网络内也没事
520 | 交互完成后 客户端能在租用期内使用服务器分配的ip地址
521 |
522 | - **NAT网络地址转换**
523 |
524 | **网络地址与端口转换 NAPT**两个不同的私有ip可以转换为一个公有ip以不同的端口号进行区分 会生成相应的路由转换表
525 |
526 | - **ICMP** 全称是 **Internet Control Message Protocol**,也就是**互联网控制报文协议**。 从哪里丢失 就从哪里发回去
527 | 分为两类
528 | 一类用于诊断的查询消息 也就是查询报文类型
529 | 另一类通知出错原因的错误消息 也就是差错报文类型
530 |
531 | - **IGMP是因特网组管理协议,工作在主机(组播成员)和最后一跳路由之间**
532 |
533 | - **ping** 用的是ICMP查询报文
534 | **traceroute** 用的是ICMP差错报文
535 |
--------------------------------------------------------------------------------