<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ariston</title>
    <description>The latest articles on DEV Community by Ariston (@weltlgit).</description>
    <link>https://dev.to/weltlgit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1218578%2F162f3047-8942-4c7e-954f-96d69e40e9cc.png</url>
      <title>DEV Community: Ariston</title>
      <link>https://dev.to/weltlgit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/weltlgit"/>
    <language>en</language>
    <item>
      <title>Craking the code interview</title>
      <dc:creator>Ariston</dc:creator>
      <pubDate>Fri, 23 Feb 2024 09:18:35 +0000</pubDate>
      <link>https://dev.to/weltlgit/craking-the-code-interview-4mkl</link>
      <guid>https://dev.to/weltlgit/craking-the-code-interview-4mkl</guid>
      <description>&lt;h1&gt;
  
  
  第五章 行为面试题
&lt;/h1&gt;

&lt;h2&gt;
  
  
  5.1 面试准备清单
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhxrjd4amgel45snr0fdx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhxrjd4amgel45snr0fdx.png" alt="Image description" width="599" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1.1 你有哪些缺点
&lt;/h3&gt;

&lt;p&gt;有时候，我对细节不够重视。好的一面是我反应迅速，执行力&lt;br&gt;
强，但不免会因为粗心大意而犯错。有鉴于此，我总是会找其他同&lt;br&gt;
事帮忙检查自己的工作，确保不出问题。&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1.2 你应该问面试官哪些问题
&lt;/h3&gt;

&lt;h4&gt;
  
  
  5.1.2.1 真实的问题
&lt;/h4&gt;

&lt;p&gt;(1) “整个团队中，测试人员、开发人员和项目经理的比例是多少？他们是如何互动的？团队怎么做项目规划？”&lt;br&gt;
(2) “你为什么来这个公司？你遇到过的最大的挑战是什么？”&lt;/p&gt;

&lt;h4&gt;
  
  
  5.1.2.2 有见地的问题
&lt;/h4&gt;

&lt;p&gt;(1) “我注意到你们使用了X技术，请问你们是如何处理Y问题的？”&lt;br&gt;
(2) “为什么你们的产品选择使用X协议而不是Y协议？据我所知，虽然X有A、B、C等几大好处，但因为存在D问题，很多公司并未采用该协议。”&lt;br&gt;
只有事先对该公司做过充分调研，才问得出这类有深度的问题。&lt;/p&gt;

&lt;h4&gt;
  
  
  5.1.2.3 富有激情的问题
&lt;/h4&gt;

&lt;p&gt;(1) “我对可扩展性很感兴趣，想要了解更多。有哪些机会可以学习这方面的知识？”&lt;br&gt;
(2) “我对X技术不是太熟悉，不过听上去是个不错的解决方案。您能给我多讲讲它的工作原理吗？”&lt;/p&gt;

&lt;h2&gt;
  
  
  5.2 掌握项目所用的技术
&lt;/h2&gt;

&lt;p&gt;有挑战性（不仅仅让你学到很多）。&lt;br&gt;
你是主力（最好负责具有挑战性的部分）。&lt;br&gt;
你能畅谈技术部分。&lt;/p&gt;

&lt;h2&gt;
  
  
  5.3 如何应对
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5.3.1 力求具体，切忌自大
&lt;/h3&gt;

&lt;p&gt;具体也就是只陈述事实，剩下的留给面试官自己去解读。例如，相比于干巴巴地说“我做了所有最难的工作”，不如就其具体工作展开描述。&lt;/p&gt;

&lt;h3&gt;
  
  
  5.3.2 省略细枝末节
&lt;/h3&gt;

&lt;p&gt;例如：&lt;br&gt;
“在研究最常见的用户行为并应用Rabin-Karp算法后，我设计了一种&lt;br&gt;
新算法，可以在90% 的情况下将搜索操作的时间复杂度由 降&lt;br&gt;
至 。您要是感兴趣的话，我可以详细说明。”该回答言简意赅，重点突出，要是面试官对实现细节感兴趣，他会主动询问。&lt;/p&gt;

&lt;h3&gt;
  
  
  5.3.3 多谈自己
&lt;/h3&gt;

&lt;p&gt;省略团队，说的都是针对个人的。&lt;/p&gt;

&lt;h3&gt;
  
  
  5.3.4 回答条例清晰
&lt;/h3&gt;

&lt;p&gt;主题先行法与S.A.R.法。&lt;/p&gt;

&lt;h4&gt;
  
  
  5.3.4.1主题先行法
&lt;/h4&gt;

&lt;p&gt;主题先行法即开门见山，直奔主题，回答简洁明了。&lt;br&gt;
以下是一个例子。&lt;br&gt;
面试官：“给我举个例子，讲一讲你如何说服一群人做出重大改&lt;br&gt;
变。”&lt;br&gt;
求职者：“好的，我在学校提出过一个让本科生授课的想法，并成&lt;br&gt;
功说服学校采纳该建议。起初，学校规定……”&lt;br&gt;
主题先行法可以快速抓住面试官的注意力，让他了解事情梗概。这也有&lt;br&gt;
助于你不偏离主题，因为你早已开门见山地点明主旨。&lt;/p&gt;

&lt;h4&gt;
  
  
  5.3.4.2 S.A.R.法
&lt;/h4&gt;

&lt;p&gt;S.A.R.法是指先描述情景（situation），然后解释你采取的行动&lt;br&gt;
（action），最后陈述结果（result）。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8y87ec4nywuceqv63ed6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8y87ec4nywuceqv63ed6.png" alt="Image description" width="603" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5.3.5 行动是关键
&lt;/h3&gt;

&lt;p&gt;我们应当重点谈行动，例如，我做了三件事，首先，我.....。这样更好&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Unix高级环境编程之文件和目录</title>
      <dc:creator>Ariston</dc:creator>
      <pubDate>Fri, 23 Feb 2024 08:09:11 +0000</pubDate>
      <link>https://dev.to/weltlgit/unixgao-ji-huan-jing-bian-cheng-zhi-wen-jian-he-mu-lu-npi</link>
      <guid>https://dev.to/weltlgit/unixgao-ji-huan-jing-bian-cheng-zhi-wen-jian-he-mu-lu-npi</guid>
      <description>&lt;h1&gt;
  
  
  引言
&lt;/h1&gt;

&lt;p&gt;从stat函数开始，诸葛说明stat结构中的每一个成员了解文件的所有属性。将说明修改这些属性的各个函数，更详细地说明UNIX文件系统的结构以及符号链接&lt;/p&gt;

&lt;h1&gt;
  
  
  函数stat、fstat、fstatat和lstat
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5c2k9e2nsxt0yrde6rs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5c2k9e2nsxt0yrde6rs.png" alt="Image description" width="766" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;给出pathname，stat函数将返回与此文件有关的信息结构。fstat获得fd上打开文件的有关信息，lstat类似于stat，但是当命名的文件是符号链接时，lstat返回符号链接的有关信息而不是该符号链接引用的文件的信息。&lt;/p&gt;

&lt;p&gt;fstatat允许通过文件描述符和相对路径名指定要获取信息的文件。&lt;br&gt;
dirfd：一个打开的目录的文件描述符，相对路径名pathname的起始点。如果pathname是绝对路径，则dirfd被忽略。&lt;br&gt;
pathname：要获取状态信息的文件的路径名。如果pathname是绝对路径，dirfd通常被设置为AT_FDCWD。&lt;br&gt;
statbuf：指向stat结构的指针，该结构用于存储文件的状态信息。&lt;br&gt;
flags：可以是零或者以下一个或多个标志的组合，影响函数的行为：&lt;br&gt;
AT_SYMLINK_NOFOLLOW：不要解引用符号链接，而是返回关于链接本身的信息。&lt;br&gt;
AT_NO_AUTOMOUNT：阻止自动挂载触发。&lt;br&gt;
AT_EMPTY_PATH：允许pathname是空字符串，这种情况下会返回dirfd所指向对象的状态。&lt;/p&gt;

&lt;p&gt;返回值：&lt;br&gt;
成功时，返回0，statbuf结构会被填充。&lt;br&gt;
失败时，返回-1，并设置errno以指示错误原因，如EACCES、EBADF、EFAULT、ENOENT等。&lt;/p&gt;

&lt;p&gt;stat结构：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;stat&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;dev_t&lt;/span&gt;     &lt;span class="n"&gt;st_dev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// 文件的设备ID&lt;/span&gt;
    &lt;span class="n"&gt;ino_t&lt;/span&gt;     &lt;span class="n"&gt;st_ino&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// 节点&lt;/span&gt;
    &lt;span class="n"&gt;mode_t&lt;/span&gt;    &lt;span class="n"&gt;st_mode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// 文件的类型和存储的权限&lt;/span&gt;
    &lt;span class="n"&gt;nlink_t&lt;/span&gt;   &lt;span class="n"&gt;st_nlink&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// 硬链接的数量&lt;/span&gt;
    &lt;span class="n"&gt;uid_t&lt;/span&gt;     &lt;span class="n"&gt;st_uid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// 所有者的用户ID&lt;/span&gt;
    &lt;span class="n"&gt;gid_t&lt;/span&gt;     &lt;span class="n"&gt;st_gid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// 所有者的组ID&lt;/span&gt;
    &lt;span class="n"&gt;dev_t&lt;/span&gt;     &lt;span class="n"&gt;st_rdev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// 设备ID（如果是特殊文件）&lt;/span&gt;
    &lt;span class="kt"&gt;off_t&lt;/span&gt;     &lt;span class="n"&gt;st_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// 总大小，以字节为单位&lt;/span&gt;
    &lt;span class="n"&gt;blksize_t&lt;/span&gt; &lt;span class="n"&gt;st_blksize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 文件系统的I/O块大小&lt;/span&gt;
    &lt;span class="n"&gt;blkcnt_t&lt;/span&gt;  &lt;span class="n"&gt;st_blocks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// 分配的512B块的数量&lt;/span&gt;

    &lt;span class="c1"&gt;// 访问和修改时间戳&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;timespec&lt;/span&gt; &lt;span class="n"&gt;st_atim&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// 最后访问时间&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;timespec&lt;/span&gt; &lt;span class="n"&gt;st_mtim&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// 最后修改时间&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;timespec&lt;/span&gt; &lt;span class="n"&gt;st_ctim&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// 最后状态改变时间&lt;/span&gt;

    &lt;span class="c1"&gt;// ...可能还有其他的字段...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;time_t&lt;/span&gt; &lt;span class="n"&gt;tv_sec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;tv_nsec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="c1"&gt;//timespec至少包含的两个字段&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;使用stat函数最多的地方可能就是ls -l。获得文件所有信息。&lt;/p&gt;

&lt;h1&gt;
  
  
  4.3 文件类型
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1.普通文件
&lt;/h2&gt;

&lt;p&gt;包含了某种形式的数据。&lt;/p&gt;

&lt;h2&gt;
  
  
  2.目录文件
&lt;/h2&gt;

&lt;p&gt;包含了其他文件的名字以及指向与这些文件有关信息的指针。对一个目录文件具有读权限的任意进程都可以读该目录的内容。进程必须要用本章介绍的函数才能更改目录。&lt;/p&gt;

&lt;h2&gt;
  
  
  3.块特殊文件
&lt;/h2&gt;

&lt;p&gt;提供对设备带缓冲的访问，每次以固定长度为单位进行&lt;/p&gt;

&lt;h2&gt;
  
  
  4.字符特殊文件
&lt;/h2&gt;

&lt;p&gt;提供对设备不带缓冲的访问，每次访问长度可变。系统中所有设备要么是字符特殊文件，要么是块特殊文件。&lt;/p&gt;

&lt;h2&gt;
  
  
  5.FIFO
&lt;/h2&gt;

&lt;p&gt;用于进程间通信，有时被称为命名管道（named pipe）&lt;/p&gt;

&lt;h2&gt;
  
  
  6.套接字
&lt;/h2&gt;

&lt;p&gt;用于进程间网络通信，也可以用于进程间非网络通信&lt;/p&gt;

&lt;h2&gt;
  
  
  7.符号链接
&lt;/h2&gt;

&lt;p&gt;这种类型的文件指向另一个文件，17节会更多描述符号链接&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5y5l5ffhan69yr32jbm7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5y5l5ffhan69yr32jbm7.png" alt="Image description" width="261" height="68"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>离散数学</title>
      <dc:creator>Ariston</dc:creator>
      <pubDate>Fri, 23 Feb 2024 04:36:36 +0000</pubDate>
      <link>https://dev.to/weltlgit/chi-san-shu-xue-bh0</link>
      <guid>https://dev.to/weltlgit/chi-san-shu-xue-bh0</guid>
      <description>&lt;p&gt;这门课的五个重要主题：数学推理、组合分析、离散结构、算法思考以及应用和建模。&lt;br&gt;
数学推理：理解数学推理、理解和构造数学证明。数理推理是证明的基础。数学归纳则是用很多例子来介绍的。&lt;/p&gt;

&lt;p&gt;组合分析：解题的重要技巧是技术或枚举对象的能力（计数和枚举就是数一数有多少种可能的方法去做某件事，组合分析就是在这些可能的方法中找出有特定条件的那些方法），我们重点用组合分析而不用公式。&lt;/p&gt;

&lt;p&gt;离散结构：表示离散对象和离散对象之间的关系，包括集合、置换、关系、图、数、有限状态机。&lt;/p&gt;

&lt;p&gt;算法思考：描述了算法就可以构造计算机程序了。&lt;/p&gt;

&lt;p&gt;应用与建模：解决实际问题。&lt;/p&gt;

&lt;p&gt;还是要独立的解题，然后才能看课后的答案。&lt;/p&gt;

&lt;h1&gt;
  
  
  第一章 基础：逻辑、集合和函数
&lt;/h1&gt;

&lt;p&gt;逻辑：比如下面这句话 存在一个大于100且是2的幂的整数&lt;br&gt;
所有的离散结构都从集合构造而来，集合指的是一组对象。&lt;/p&gt;

&lt;h2&gt;
  
  
  1.1 逻辑
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1.1 引言
&lt;/h3&gt;

&lt;p&gt;逻辑规则给出数学语句的准确含义，这些规则用来区分有效无效的数学论证。&lt;/p&gt;

&lt;h3&gt;
  
  
  1.1.2 命题
&lt;/h3&gt;

&lt;p&gt;一个命题是真或假的语句，但不能既真又假。&lt;br&gt;
且或，这里的或一般是同或，还有异或，异或是两个恰有一个为真时是真，否则为假。&lt;br&gt;
合取：p ^ q为p和q的合取&lt;br&gt;
析取：p 或 q成为p和q的析取&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd1g4tao3vdw8l0tlq5vj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd1g4tao3vdw8l0tlq5vj.png" alt="Image description" width="335" height="171"&gt;&lt;/a&gt;&lt;br&gt;
这个比较反常理，如下，&lt;br&gt;
假设有这样一个规则：“如果外面下雨，那么街道就会湿。”现在让我们来看看逆向的情况。&lt;/p&gt;

&lt;p&gt;如果我们说“如果外面没有下雨，街道就会干燥。”这听起来很有道理，对吗？因为通常情况下，如果没下雨，街道自然是干燥的。&lt;/p&gt;

&lt;p&gt;但是，如果我们说“如果外面没有下雨，街道就会湿。”这听起来似乎不太对，因为我们的常识告诉我们，没有雨水街道应该是干的。&lt;/p&gt;

&lt;p&gt;然而，在逻辑学中，我们说的是一种可能性，而不是实际情况。这就意味着，如果我们假定了一个不真实的情况——比如外面没有下雨，但是街道确实是湿的，那么这个不真实的情况就可以让整个命题成立。可能街道是湿的是因为有人洒了水，或者有其他的原因。&lt;/p&gt;

&lt;p&gt;所以在逻辑学里，“如果非 p，则 q”这句话是一种表达可能性的方式，而不一定反映实际情况。这种说法只是告诉我们，如果假设成立，那么结果也会成立，不管这个假设是真的还是假的。&lt;br&gt;
蕴含就是上述说的p-&amp;gt;q&lt;br&gt;
双蕴含就是p &amp;lt;-&amp;gt; q&lt;/p&gt;

&lt;h3&gt;
  
  
  1.1.3 翻译语言的句子
&lt;/h3&gt;

&lt;p&gt;语言常有二义性，把句子译成逻辑表达式可以消除歧义。&lt;br&gt;
详见书中例子，30页&lt;/p&gt;

</description>
    </item>
    <item>
      <title>编译原理（龙书）</title>
      <dc:creator>Ariston</dc:creator>
      <pubDate>Fri, 23 Feb 2024 03:16:06 +0000</pubDate>
      <link>https://dev.to/weltlgit/bian-yi-yuan-li-long-shu--5b8p</link>
      <guid>https://dev.to/weltlgit/bian-yi-yuan-li-long-shu--5b8p</guid>
      <description>&lt;p&gt;这本书的内容挺多的，书中推荐至少两个学期，所以我们不可能短时间内看完，要打长期战。&lt;/p&gt;

&lt;h1&gt;
  
  
  第一章 引论
&lt;/h1&gt;

&lt;p&gt;研究编译器的编写将涉及到程序设计语言、计算机体系结构、&lt;br&gt;
形式语言理论、算法和软件工程。&lt;/p&gt;

&lt;h2&gt;
  
  
  1.1 语言处理器
&lt;/h2&gt;

&lt;p&gt;编译器本质是程序，可以阅读某一种语言编写的程序，并把程序翻译成一个用另一种语言（目标语言）编写的程序。重要任务是在翻译过程中发现源程序的错误&lt;/p&gt;

</description>
    </item>
    <item>
      <title>MSBuild</title>
      <dc:creator>Ariston</dc:creator>
      <pubDate>Fri, 23 Feb 2024 02:23:11 +0000</pubDate>
      <link>https://dev.to/weltlgit/msbuild-1b43</link>
      <guid>https://dev.to/weltlgit/msbuild-1b43</guid>
      <description>&lt;h1&gt;
  
  
  MSBuild是什么？
&lt;/h1&gt;

&lt;p&gt;Microsoft Build Engine，用于构建应用程序的平台，.proj文件就是MSBuild提供的，这个XML格式的文件，含有项目所包含的文件，生成配置，输出配置等。当把文件或者图片添加到项目中，就会在这里添加一个描述，反之则删除一个描述，在项目属性页作的配置也会在这里存储？（这句话没明白是什么意思）&lt;/p&gt;

&lt;h1&gt;
  
  
  MSBuild的基本概念
&lt;/h1&gt;

&lt;p&gt;MSBuild有四个基本块（属性、项、任务、目标）&lt;br&gt;
MSBuild属性：属性是一些键值对、一定要包含在PropertyGroup元素内部&lt;br&gt;
MSBuild项：存储一些项目文件信息、以及文件元数据信息&lt;br&gt;
MSBuild任务：Build过程中的一些原子操作（如CSC、MakeDir）。&lt;br&gt;
MSBuild目标：&lt;br&gt;
一句话总结MSBuild，利用配置信息对项目文件实施特定顺序的操作。&lt;/p&gt;
&lt;h1&gt;
  
  
  MSBuild属性
&lt;/h1&gt;

&lt;p&gt;属性声明方式：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="o"&gt;?&amp;gt;&lt;/span&gt;
 &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="err"&gt;根元素，表示一个项目&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
 &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="n"&gt;DefaultTargets&lt;/span&gt;&lt;span class="err"&gt;用于定默认执行的目标&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
 &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Project&lt;/span&gt; &lt;span class="n"&gt;DefaultTargets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"build"&lt;/span&gt; &lt;span class="n"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.microsoft.com/developer/msbuild/2003"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="mi"&gt;5&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="err"&gt;属性都要包含在&lt;/span&gt;&lt;span class="n"&gt;PropertyGroup&lt;/span&gt;&lt;span class="err"&gt;元素内部&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
 &lt;span class="mi"&gt;6&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PropertyGroup&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="mi"&gt;7&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="err"&gt;声明一个&lt;/span&gt;&lt;span class="s"&gt;"linianhui"&lt;/span&gt;&lt;span class="err"&gt;属性，其值为&lt;/span&gt;&lt;span class="s"&gt;"hello world"&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
 &lt;span class="mi"&gt;8&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;linianhui&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="n"&gt;world&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;linianhui&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="mi"&gt;9&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;PropertyGroup&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="err"&gt;目标&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Target&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"build"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="mi"&gt;12&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="n"&gt;MSBuild&lt;/span&gt;&lt;span class="err"&gt;提供的一个内置任务，用于生成记录信息用$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;属性名&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;来引用属性的值&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="mi"&gt;13&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"$(linianhui)"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="mi"&gt;14&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Target&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Project&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;这里面的DefaultTargets和xmlns都是固定的，我们就照抄就好&lt;br&gt;
可以看出来，属性都是键值对，并且只在PropertyGroup内部，属性可以被引用。&lt;/p&gt;
&lt;h1&gt;
  
  
  MSBuild项
&lt;/h1&gt;

&lt;p&gt;项声明方式：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="o"&gt;?&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Project&lt;/span&gt; &lt;span class="n"&gt;DefaultTargets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"build"&lt;/span&gt; &lt;span class="n"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.microsoft.com/developer/msbuild/2003"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="err"&gt;项都要包含在&lt;/span&gt;&lt;span class="n"&gt;ItemGroup&lt;/span&gt;&lt;span class="err"&gt;元素内部&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ItemGroup&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="err"&gt;声明一个&lt;/span&gt;&lt;span class="s"&gt;"CSFile"&lt;/span&gt;&lt;span class="err"&gt;的项，&lt;/span&gt;&lt;span class="n"&gt;Include&lt;/span&gt;&lt;span class="err"&gt;表示引入&lt;/span&gt;&lt;span class="s"&gt;"csfile1.cs"&lt;/span&gt;&lt;span class="err"&gt;文件&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CSFile&lt;/span&gt; &lt;span class="n"&gt;Include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"csfile1.cs"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="err"&gt;表示项的元数据（附加信息）&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mf"&gt;1.0.0.0&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;CSFile&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="err"&gt;也可用&lt;/span&gt;&lt;span class="s"&gt;";"&lt;/span&gt;&lt;span class="err"&gt;一次引入多个文件&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CSFile&lt;/span&gt; &lt;span class="n"&gt;Include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"csfile2.cs;csfile3.cs"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;ItemGroup&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Target&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"build"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="err"&gt;@引用项的值，默认以&lt;/span&gt;&lt;span class="s"&gt;";"&lt;/span&gt;&lt;span class="err"&gt;分割开&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="err"&gt;输出&lt;/span&gt;&lt;span class="s"&gt;"csfile1.cs;csfile2.cs;csfile3.cs"&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"@(CSFile)"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="err"&gt;可以加第二个参数替换默认的&lt;/span&gt;&lt;span class="s"&gt;";"&lt;/span&gt;&lt;span class="err"&gt;分隔符&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="err"&gt;输出&lt;/span&gt;&lt;span class="s"&gt;"csfile1.cs+csfile2.cs+csfile3.cs"&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"@(CSFile,'+')"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;!--%&lt;/span&gt;&lt;span class="err"&gt;引用项的元数据，输出&lt;/span&gt;&lt;span class="s"&gt;"1.0.0.0"&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"%(CSFile.Version)"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Target&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Project&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;我们可以看到所有的项都要包含在ItemGroup内部，其余细节见代码注释&lt;/p&gt;

&lt;h1&gt;
  
  
  MSBuild 任务
&lt;/h1&gt;

&lt;p&gt;上面的Messgae就是一个任务，用于打印信息，大多任务都是有输出信息的，这些信息可以通过OutPut元素存储在属性或者项中，&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Game Scripting Mastery</title>
      <dc:creator>Ariston</dc:creator>
      <pubDate>Mon, 19 Feb 2024 03:36:22 +0000</pubDate>
      <link>https://dev.to/weltlgit/game-scripting-mastery-41j9</link>
      <guid>https://dev.to/weltlgit/game-scripting-mastery-41j9</guid>
      <description>&lt;p&gt;百分之九十的3D游戏都是先开发一个游戏引擎，然后用脚本语言实现引擎接口在虚拟机上，actual game logic is more important。&lt;br&gt;
this book is talking about compiler theory,virtual machines, and multithreading。&lt;br&gt;
By the end of the book you’ll be able to write a compiler and a virtual machine&lt;/p&gt;

&lt;p&gt;the true challenge will be immersing players in settings and worlds that exert a genuine sense of atmosphere and organic life&lt;/p&gt;

&lt;p&gt;A game should have compellingly animated detail and believable responsiveness&lt;/p&gt;

&lt;p&gt;The point is to figure out why.&lt;/p&gt;

&lt;h1&gt;
  
  
  Part One Scripting Fundamentals
&lt;/h1&gt;

&lt;p&gt;The majority of this material won't do you much&lt;br&gt;
good if you don't know what scripting is or why it's important. Like I said, you can follow&lt;br&gt;
this book whether or not you've even heard of scripting. The introduction provides&lt;br&gt;
enough background information to get you up to speed quick&lt;/p&gt;

&lt;h2&gt;
  
  
  Charpter 1 An Introduction To Scripting
&lt;/h2&gt;

&lt;p&gt;■ An overview of what scripting is and how it works.&lt;br&gt;
■ Discussion on the fundamental types of scripting systems.&lt;br&gt;
■ Brief coverage of existing scripting systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Scripting？
&lt;/h3&gt;

&lt;p&gt;Firstly introduce RPG and cover the basic tasks involved in its production.&lt;br&gt;
The first thing we need is the game engine（Details in the book）.Next up we are going to need garphics.Then&lt;br&gt;
music and sound.&lt;/p&gt;

&lt;h3&gt;
  
  
  STRUCTURED GAME CONTENT-A SIMPLE APPROACH
&lt;/h3&gt;

&lt;p&gt;Firstly coding all data into the engine.&lt;/p&gt;

&lt;p&gt;Think about it this way—coding game content directly into your engine is a little like wearing a&lt;br&gt;
tuxedo every day of your life&lt;/p&gt;

&lt;h1&gt;
  
  
  Part Two Command-Based Scripting
&lt;/h1&gt;

&lt;p&gt;Developing a complete, high-level scripting system&lt;br&gt;
for a procedural language is a complex task. A very complex task. So, we start off by setting our sights a bit lower and implementing what I like to call a "command-based language." As you'll see, command-based languages are dead simple to implement and&lt;br&gt;
capable of performing rather interesting tasks&lt;/p&gt;

&lt;h1&gt;
  
  
  Part Three Introduction to Procedural Scripting Languages
&lt;/h1&gt;

&lt;p&gt;Part 3 is where things start to heat up, as we get our feet wet with real world, high-level scripting. Also covered in this section are complete tutorials on using the Lua, Python and Tcl languages, as well as integrating their associated runtime environments with a host application&lt;/p&gt;

&lt;h1&gt;
  
  
  Part Four Designing and Implementing a Low-Level Langauge
&lt;/h1&gt;

&lt;p&gt;At the bottom of our scripting system will lie an assembly language and corresponding machine code (or bytecode). The design and implementation of this low-level environment will provide a vital foundation for the later chapters&lt;/p&gt;

&lt;h1&gt;
  
  
  Part Five Designing and Implementing a Virtual Machine
&lt;/h1&gt;

&lt;p&gt;Scripts—even compiled ones—don't matter much if you don't have a way to run them. This section of the book&lt;br&gt;
covers the design and implementation of a feature-packed virtual machine that's ready to be dropped into a game engine&lt;/p&gt;

&lt;h1&gt;
  
  
  Part Six Compiling High-Level Code
&lt;/h1&gt;

&lt;p&gt;The belly of the beast itself. Executing compiled&lt;br&gt;
bytecode is one thing, but being able to compile and ultimately run a high-level, procedural language of your own design is what real scripting is all about&lt;/p&gt;

&lt;h1&gt;
  
  
  Part Seven Completing Your Training
&lt;/h1&gt;

&lt;p&gt;Once you've earned your stripes, it's time to direct that knowledge somewhere. This final section aims to clear up any questions you may have in regards to furthering your study. You'll also see how the scripting system designed throughout the course of the book was applied to a complete game.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>国内访问github</title>
      <dc:creator>Ariston</dc:creator>
      <pubDate>Mon, 29 Jan 2024 15:36:18 +0000</pubDate>
      <link>https://dev.to/weltlgit/guo-nei-fang-wen-github-3kc1</link>
      <guid>https://dev.to/weltlgit/guo-nei-fang-wen-github-3kc1</guid>
      <description>&lt;p&gt;140.82.113.26 alive.github.com&lt;br&gt;
140.82.114.25 live.github.com&lt;br&gt;
185.199.108.154 github.githubassets.com&lt;br&gt;
140.82.114.21 central.github.com&lt;br&gt;
185.199.110.133 desktop.githubusercontent.com&lt;br&gt;
185.199.111.153 assets-cdn.github.com&lt;br&gt;
185.199.109.133 camo.githubusercontent.com&lt;br&gt;
185.199.108.133 github.map.fastly.net&lt;br&gt;
146.75.121.194 github.global.ssl.fastly.net&lt;br&gt;
140.82.121.3 gist.github.com&lt;br&gt;
185.199.111.153 github.io&lt;br&gt;
140.82.121.3 github.com&lt;br&gt;
192.0.66.2 github.blog&lt;br&gt;
140.82.121.5 api.github.com&lt;br&gt;
185.199.111.133 raw.githubusercontent.com&lt;br&gt;
185.199.108.133 user-images.githubusercontent.com&lt;br&gt;
185.199.111.133 favicons.githubusercontent.com&lt;br&gt;
185.199.108.133 avatars5.githubusercontent.com&lt;br&gt;
185.199.109.133 avatars4.githubusercontent.com&lt;br&gt;
185.199.108.133 avatars3.githubusercontent.com&lt;br&gt;
185.199.111.133 avatars2.githubusercontent.com&lt;br&gt;
185.199.108.133 avatars1.githubusercontent.com&lt;br&gt;
185.199.109.133 avatars0.githubusercontent.com&lt;br&gt;
185.199.111.133 avatars.githubusercontent.com&lt;br&gt;
140.82.121.10 codeload.github.com&lt;br&gt;
54.231.140.1 github-cloud.s3.amazonaws.com&lt;br&gt;
3.5.25.149 github-com.s3.amazonaws.com&lt;br&gt;
52.217.47.12 github-production-release-asset-2e65be.s3.amazonaws.com&lt;br&gt;
52.217.18.236 github-production-user-asset-6210df.s3.amazonaws.com&lt;br&gt;
52.217.173.185 github-production-repository-file-5c1aeb.s3.amazonaws.com&lt;br&gt;
185.199.109.153 githubstatus.com&lt;br&gt;
140.82.114.18 github.community&lt;br&gt;
51.137.3.17 github.dev&lt;br&gt;
140.82.112.22 collector.github.com&lt;br&gt;
13.107.42.16 pipelines.actions.githubusercontent.com&lt;br&gt;
185.199.110.133 media.githubusercontent.com&lt;br&gt;
185.199.108.133 cloud.githubusercontent.com&lt;br&gt;
185.199.111.133 objects.githubusercontent.com&lt;/p&gt;

&lt;p&gt;把这些复制到hosts里面，然后给自己的github配置一个ssh就ok了&lt;/p&gt;

</description>
    </item>
    <item>
      <title>1234</title>
      <dc:creator>Ariston</dc:creator>
      <pubDate>Fri, 26 Jan 2024 09:53:28 +0000</pubDate>
      <link>https://dev.to/weltlgit/1234-2eko</link>
      <guid>https://dev.to/weltlgit/1234-2eko</guid>
      <description>&lt;p&gt;ril：radio interface layer，操作系统和无线电硬件中间的一个层，让OS和无线电硬件进行通信。&lt;/p&gt;

&lt;h1&gt;
  
  
  esim.h
&lt;/h1&gt;

&lt;p&gt;ProfileT 相当于一张卡的配置文件，里面有卡的别称，状态，以及供应商&lt;/p&gt;

&lt;h1&gt;
  
  
  esim cpp
&lt;/h1&gt;

&lt;p&gt;overview：设计esim卡管理得复杂系统的一部分，主要功能包括处理eSIM配置文件&lt;br&gt;
的各种操作，如获取信息、更新、备份和恢复等。它通过发送AT命令与电信硬件交互&lt;br&gt;
，并使用JSON格式存储数据。&lt;/p&gt;

&lt;h2&gt;
  
  
  namespace esim
&lt;/h2&gt;

&lt;p&gt;一个结构体，SIMT，定义了iccid code还有apn，三个字符串，然后&lt;br&gt;
to_json和from_json，分别是把struct SIMT转换成json SIMT，json SIMT转换成struct SIMT&lt;br&gt;
std::string iccid：ICCID（Integrated Circuit Card Identifier）是一个唯一标识SIM卡的序列号。它是SIM卡在全球移动网络中的唯一标识符。&lt;br&gt;
std::string code：这可能是与SIM卡或eSIM相关的某种代码，例如激活码、访问码或其他类型的识别码。&lt;br&gt;
std::string apn：APN（Access Point Name）是用于连接到移动互联网的网络接入点的名称。这通常用于配置设备的移动数据连接。&lt;/p&gt;

&lt;h2&gt;
  
  
  makeBackup函数
&lt;/h2&gt;

&lt;p&gt;如果当前没有sim卡，那么删除BACK_FILE文件，如果有sim卡，则把sims卡信息以json格式加到BACK_FILE中。&lt;/p&gt;

&lt;h2&gt;
  
  
  makeRestore函数
&lt;/h2&gt;

&lt;p&gt;如果当前没有备份文件，那么直接返回，如果有备份文件，把BACK_FILE中的sim卡信息存到sims中&lt;/p&gt;

&lt;h2&gt;
  
  
  isProfileIncluded函数
&lt;/h2&gt;

&lt;p&gt;检测profile是否存在于profiles中，第二个参数是否存在于第一个参数中，存在返回true不存在返回false&lt;/p&gt;

&lt;h2&gt;
  
  
  findNewProfile函数
&lt;/h2&gt;

&lt;p&gt;给出两个profiles，一个是新的一个是旧的，检查新的和旧的是否元素相同，如果不相同，返回不相同的profile给第三个参数，然后只要找到一个直接就结束&lt;/p&gt;

&lt;h2&gt;
  
  
  handleProfileEnabled函数
&lt;/h2&gt;

&lt;p&gt;static void handleProfileEnabled(const std::string&amp;amp; iccid, const std::string&amp;amp; apn);&lt;br&gt;
如果apn不空，更新apn。&lt;br&gt;
然后通过esim_get_profile_list来获取配置文件列表，把然后存储到profiles中，&lt;br&gt;
作用：当一张sim卡启用时，更新APN和提供商设置，然后重启来应用新的网络配置。&lt;/p&gt;

&lt;h2&gt;
  
  
  handleProfileOpration函数
&lt;/h2&gt;

&lt;p&gt;static bool handleProfileOpration(const std::string&amp;amp; operation)；&lt;br&gt;
传入一个操作，成功返回true，失败返回false&lt;/p&gt;

&lt;h2&gt;
  
  
  esim_get_eid函数
&lt;/h2&gt;

&lt;p&gt;bool esim_get_eid(std::string&amp;amp; eid);&lt;br&gt;
传入一个空的eid，获得一个当前启用的eid&lt;/p&gt;

&lt;h2&gt;
  
  
  esim_get_profile_list函数
&lt;/h2&gt;

&lt;p&gt;bool esim_get_profile_list(std::vector&lt;a&gt;esim::ProfileT&lt;/a&gt;&amp;amp; profiles)&lt;br&gt;
从eSIM管理器查询eSIM配置文件列表，并将结果填充到profiles中。&lt;/p&gt;

&lt;h2&gt;
  
  
  esim_profile_enable函数
&lt;/h2&gt;

&lt;p&gt;bool esim_profile_enable(const std::string&amp;amp; iccid)；&lt;br&gt;
让iccid卡生效并使用，成功的话返回true，失败false&lt;br&gt;
首先遍历全局变量sims，如果我们要enable的iccid在sims中，那么直接启动，并且按照备份好的apn，&lt;br&gt;
如果没有启动那么启动就是按照空的apn来。&lt;br&gt;
本质上调了handleProfileOpration&lt;/p&gt;

&lt;h2&gt;
  
  
  esim_profile_disable函数
&lt;/h2&gt;

&lt;p&gt;bool esim_profile_disable(const std::string&amp;amp; iccid);&lt;br&gt;
禁用iccid&lt;br&gt;
本质上调了handleProfileOpration&lt;/p&gt;

&lt;h2&gt;
  
  
  esim_profile_delete函数
&lt;/h2&gt;

&lt;p&gt;bool esim_profile_disable(const std::string&amp;amp; iccid);&lt;br&gt;
删除iccid配置文件，&lt;br&gt;
本质上调了handleProfileOpration&lt;/p&gt;

&lt;h2&gt;
  
  
  esim_profile_set_nickname函数
&lt;/h2&gt;

&lt;p&gt;bool esim_profile_set_nickname(const std::string&amp;amp; iccid, const std::string&amp;amp; nikename);&lt;br&gt;
给iccid的配置文件中修改nickename&lt;/p&gt;

&lt;h2&gt;
  
  
  esim_profile_download_enable函数
&lt;/h2&gt;

&lt;p&gt;bool esim_profile_download_enable(const std::string&amp;amp; code, const std::string&amp;amp; apn, bool enable);&lt;br&gt;
用激活码来获取配置文件，并且按需应用这个esim卡，相当于买了张手机卡，给张激活码，然后获取一张ccid就是这样。&lt;/p&gt;

&lt;h1&gt;
  
  
  esim_message.cpp
&lt;/h1&gt;

&lt;p&gt;总结来说，这个文件是eSIM管理系统的核心，负责接收、解析和执行与eSIM配置相关的各种操作。这些操作包括下载、启用、禁用和删除eSIM配置文件，以及与设备的通信模块进行交互来实施这些操作。&lt;/p&gt;

&lt;h1&gt;
  
  
  config.cpp
&lt;/h1&gt;

&lt;p&gt;这个文件构建了一个完整的配置管理系统，用于处理和维护设备的配置。它允许从文件中读取配置，将配置保存到文件，并提供了访问和修改配置的接口。此外，它还包括查找设备特定路径和格式化时间数据的功能。这样的系统对于管理设备的运行状态和行为至关重要，尤其是在需要根据用户偏好或不同环境条件动态调整行为的情况下。&lt;/p&gt;

&lt;h1&gt;
  
  
  at_tok.cpp
&lt;/h1&gt;

&lt;p&gt;解析和处理AT命令响应的C语言函数库。AT命令是用于控制电话调制解调器和相关设备的命令语言。调制解调器是一种设备，它能让计算机通过电话线（或类似的通信方式）发送和接收数据。&lt;/p&gt;

&lt;p&gt;int at_tok_start(char** p_cur)&lt;br&gt;
功能: 初始化AT命令响应字符串的解析过程。&lt;br&gt;
参数: p_cur 是一个指向AT响应字符串的指针。&lt;br&gt;
返回值: 成功时返回 0，如果 p_cur 是一个无效的指针或字符串不包含 ':' 字符，则返回 -1。&lt;br&gt;
操作: 此函数查找字符串中的第一个冒号 (':') 并将 p_cur 更新为冒号之后的位置，以准备解析后续的令牌。&lt;/p&gt;

&lt;p&gt;static void skipWhiteSpace(char** p_cur)&lt;br&gt;
功能: 跳过字符串中的空白字符。&lt;br&gt;
参数: p_cur 是一个指向AT响应字符串的指针。&lt;br&gt;
操作: 此函数会跳过空白字符，如空格和制表符，直到遇到非空白字符或字符串结束。&lt;/p&gt;

&lt;p&gt;static void skipNextComma(char** p_cur)&lt;br&gt;
功能: 跳过下一个逗号 (',')。&lt;br&gt;
参数: p_cur 是一个指向AT响应字符串的指针。&lt;br&gt;
操作: 此函数会跳过直到下一个逗号，然后将指针移动到逗号之后的位置。&lt;/p&gt;

&lt;p&gt;static char* nextTok(char** p_cur)&lt;br&gt;
功能: 获取下一个令牌。&lt;br&gt;
参数: p_cur 是一个指向AT响应字符串的指针。&lt;br&gt;
返回值: 返回下一个令牌的指针，如果没有更多令牌，则返回 NULL。&lt;br&gt;
操作: 此函数从当前位置开始获取下一个令牌，令牌可以是被引号包围的字符串或逗号分隔的字符串片段。&lt;/p&gt;

&lt;p&gt;static int at_tok_nextint_base(char** p_cur, int* p_out, int base, int uns)&lt;br&gt;
功能: 解析下一个整数值。&lt;br&gt;
参数: p_cur 是指向字符串的指针，p_out 是存放解析结果的整数指针，base 指定数值的基数（如 10 表示十进制），uns 指定是否为无符号整数。&lt;br&gt;
返回值: 成功时返回 0，失败时返回 -1。&lt;br&gt;
操作: 从当前位置解析下一个整数值，根据 base 指定的基数进行解析。&lt;/p&gt;

&lt;p&gt;int at_tok_nextfloat(char** p_cur, float* p_out)&lt;br&gt;
功能: 解析下一个浮点数。&lt;br&gt;
参数: p_cur 是指向字符串的指针，p_out 是存放解析结果的浮点数指针。&lt;br&gt;
返回值: 成功时返回 0，失败时返回 -1。&lt;br&gt;
操作: 从当前位置解析下一个浮点数。&lt;/p&gt;

&lt;p&gt;int at_tok_nextint(char** p_cur, int* p_out)&lt;br&gt;
功能: 解析下一个十进制整数。&lt;br&gt;
参数: p_cur 是指向字符串的指针，p_out 是存放解析结果的整数指针。&lt;br&gt;
返回值: 成功时返回 0，失败时返回 -1。&lt;br&gt;
操作: 从当前位置解析下一个十进制整数。&lt;/p&gt;

&lt;p&gt;int at_tok_nexthexint(char** p_cur, int* p_out)&lt;br&gt;
功能: 解析下一个十六进制整数。&lt;br&gt;
参数: p_cur 是指向字符串的指针，p_out 是存放解析结果的整数指针。&lt;br&gt;
返回值: 成功时返回 0，失败时返回 -1。&lt;br&gt;
操作: 从当前位置解析下一个十六进制整数。&lt;/p&gt;

&lt;p&gt;int at_tok_nextbool(char** p_cur, char* p_out)&lt;br&gt;
功能: 解析下一个布尔值。&lt;br&gt;
参数: p_cur 是指向字符串的指针，p_out 是存放解析结果的布尔值指针。&lt;br&gt;
返回值: 成功时返回 0，失败时返回 -1。&lt;br&gt;
操作: 从当前位置解析下一个布尔值，期望值为 0 或 1。&lt;/p&gt;

&lt;p&gt;int at_tok_nextstr(char** p_cur, char** p_out)&lt;br&gt;
功能: 解析下一个字符串。&lt;br&gt;
参数: p_cur 是指向字符串的指针，p_out 是存放解析结果的字符串指针。&lt;br&gt;
返回值: 成功时返回 0，失败时返回 -1。&lt;br&gt;
操作: 从当前位置解析下一个字符串。&lt;/p&gt;

&lt;p&gt;int at_tok_hasmore(char** p_cur)&lt;br&gt;
功能: 检查是否还有更多令牌可供解析。&lt;br&gt;
参数: p_cur 是指向字符串的指针。&lt;br&gt;
返回值: 如果还有更多令牌，则返回 1，否则返回 0。&lt;br&gt;
操作: 检查当前位置之后是否还有更多令牌。&lt;/p&gt;

&lt;h1&gt;
  
  
  atchannel.cpp
&lt;/h1&gt;

&lt;p&gt;这个文件是Android RIL (Radio Interface Layer) 的一部分，它提供了与无线模块进行通信所需的低级功能。主要用于发送AT命令到无线模块，并接收处理响应。这对于实现手机的基本通信功能（如拨号、短信、网络连接等）至关重要。通过这个文件的函数，可以实现对无线模块的控制和状态查询，从而使得Android设备能够与移动网络进行交互。&lt;/p&gt;

&lt;p&gt;变量&lt;br&gt;
s_tid_reader: AT命令的读取线程的线程ID。&lt;br&gt;
s_fd: AT通道的文件描述符。&lt;br&gt;
s_unsolHandler: 未经请求的响应（unsolicited response）的处理函数。&lt;br&gt;
s_ATBuffer: 用于存储从AT通道读取的数据的缓冲区。&lt;br&gt;
s_ATBufferCur: 指向当前缓冲区处理位置的指针。&lt;br&gt;
s_commandmutex: 用于同步AT命令的互斥锁。&lt;br&gt;
s_commandcond: 用于AT命令的条件变量。&lt;br&gt;
s_writeMutex: 用于同步写入AT命令的互斥锁。&lt;br&gt;
s_type: 当前正在处理的AT命令的类型。&lt;br&gt;
s_responsePrefix: AT命令响应的前缀。&lt;br&gt;
s_smsPDU: 短信PDU数据。&lt;br&gt;
sp_response: AT命令响应的结构体指针。&lt;br&gt;
s_onTimeout: 超时回调函数。&lt;br&gt;
s_onReaderClosed: 读取线程关闭时的回调函数。&lt;br&gt;
s_readerClosed: 读取线程是否已关闭的标志。&lt;/p&gt;

&lt;p&gt;函数&lt;br&gt;
AT_DUMP: 用于调试时打印AT命令的缓冲区内容。&lt;br&gt;
setTimespecRelative: 设置相对于当前时间的时间结构体。&lt;br&gt;
sleepMsec: 使线程睡眠指定的毫秒数。&lt;br&gt;
addIntermediate: 添加中间响应到AT命令响应结构体中。&lt;br&gt;
isFinalResponseSuccess: 检查是否为成功的最终响应。&lt;br&gt;
isFinalResponseError: 检查是否为错误的最终响应。&lt;br&gt;
isFinalResponse: 检查是否为任何类型的最终响应。&lt;br&gt;
isSMSUnsolicited: 检查是否为短信的未经请求的响应。&lt;br&gt;
handleFinalResponse: 处理最终响应。&lt;br&gt;
handleUnsolicited: 处理未经请求的响应。&lt;br&gt;
processLine: 处理从AT通道读取的一行数据。&lt;br&gt;
findNextEOL: 在缓冲区中查找下一个行结束符。&lt;br&gt;
readline: 从AT通道读取一行。&lt;br&gt;
onReaderClosed: 处理读取线程关闭的情况。&lt;br&gt;
readerLoop: AT命令的读取循环。&lt;br&gt;
writeline: 向AT通道写入一行。&lt;br&gt;
writeCtrlZ: 写入Ctrl-Z字符到AT通道。&lt;br&gt;
clearPendingCommand: 清除挂起的AT命令。&lt;br&gt;
at_response_new: 创建新的AT响应结构体。&lt;br&gt;
at_response_free: 释放AT响应结构体。&lt;br&gt;
reverseIntermediates: 反转中间响应列表的顺序。&lt;br&gt;
at_send_command_full_nolock: 发送AT命令（无锁版本）。&lt;br&gt;
at_send_command_full: 发送AT命令（带锁版本）。&lt;br&gt;
at_send_command: 发送一个不期待中间响应的AT命令。&lt;br&gt;
at_send_command_singleline: 发送一个期待单行中间响应的AT命令。&lt;br&gt;
at_send_command_composed: 发送一个期待组合响应的AT命令。&lt;br&gt;
at_send_command_numeric: 发送一个期待数字响应的AT命令。&lt;br&gt;
at_send_command_sms: 发送一个SMS相关的AT命令。&lt;br&gt;
at_send_command_multiline: 发送一个期待多行中间响应的AT命令。&lt;br&gt;
at_set_on_timeout: 设置超时回调函数。&lt;br&gt;
at_set_on_reader_closed: 设置读取线程关闭时的回调函数。&lt;br&gt;
at_handshake: 执行与AT通道的握手操作。&lt;br&gt;
at_get_cme_error: 从AT响应中获取CME错误码。&lt;br&gt;
at_open: 在指定的文件描述符上开启AT处理。&lt;br&gt;
at_close: 关闭AT处理。&lt;/p&gt;

&lt;h1&gt;
  
  
  keypad.cpp
&lt;/h1&gt;

&lt;p&gt;这个文件提供了一个基础的框架，用于在Linux环境中处理键盘或其他按键输入设备的事件。通过创建一个专门的线程来监听指定输入设备的事件，并提供了一个机制来设置自定义的按键处理回调函数。这种设计使得程序可以灵活地集成到需要键盘输入处理的应用程序中，如嵌入式系统、游戏控制器或其他特定硬件的交互接口。&lt;/p&gt;

&lt;h1&gt;
  
  
  ril.cpp
&lt;/h1&gt;

&lt;p&gt;这个文件实现了RIL层中的事件处理机制，包括定时任务的调度和执行，以及基于事件的异步处理。它创建了一个专门的线程来运行事件循环，并提供了接口来添加、取消和执行定时的回调任务。这种机制对于需要定时或异步执行任务的无线电通信服务非常重要，比如在特定时间发送心跳信号、处理超时事件等。通过这个文件的功能，安卓系统能够更有效地管理和响应无线电层的事件和状态变更。&lt;/p&gt;

&lt;h1&gt;
  
  
  timer.cpp
&lt;/h1&gt;

&lt;p&gt;这个文件提供了一个简单的接口来处理定时器相关的操作。它允许创建定时器，设置其回调函数，修改定时器的触发时间，查询剩余时间，以及销毁定时器。这类功能在需要定时执行任务的应用程序中非常有用，例如在一定时间后触发事件、定期执行维护任务等。通过这些函数，程序可以更有效地管理定时任务，而无需手动跟踪时间或使用复杂的事件循环。&lt;/p&gt;

&lt;h1&gt;
  
  
  encrypt.cpp
&lt;/h1&gt;

&lt;p&gt;这个文件提供了一种使用AES算法加密和解密数据的方法。这种加密机制在数据传输和存储中非常有用，特别是需要保护数据不被未授权访问时。文件中的函数可以轻松地集成到需要加密功能的应用程序中，为数据传输和存储提供安全性。由于使用了Base64编码，加密后的数据也易于处理和传输。&lt;/p&gt;

&lt;h1&gt;
  
  
  sms.cpp
&lt;/h1&gt;

&lt;p&gt;这个文件是一个灵活的消息处理框架，能够接收、解析和响应不同类型的短信消息。它通过注册机制允许多种不同的消息处理逻辑，并且能够处理消息接收过程中的并发问题，确保系统在处理消息时的稳定性和可靠性。此外，该系统还包含了对系统状态的调整，如重置自动关机计时器，以响应收到的消息。&lt;/p&gt;

&lt;h1&gt;
  
  
  uart.cpp
&lt;/h1&gt;

&lt;p&gt;主要包含了用于操作UART（通用异步接收/发送器，Universal Asynchronous Receiver/Transmitter）的函数。UART是一种广泛用于串行通信的硬件设备。&lt;/p&gt;

&lt;h1&gt;
  
  
  reference-ril.cpp
&lt;/h1&gt;

&lt;p&gt;主要提供的功能是作为应用处理器（AP）端和LTE通信模块之间的接口&lt;/p&gt;

&lt;p&gt;s_state_mutex 和 s_state_cond: 用于线程同步的互斥锁和条件变量。&lt;/p&gt;

&lt;p&gt;s_closed 和 s_activated: 分别表示RIL是否关闭和是否激活的标志。&lt;/p&gt;

&lt;p&gt;s_tid_mainloop: 主循环线程的线程ID。&lt;/p&gt;

&lt;p&gt;TIMEVAL_SIMPOLL, TIMEVAL_CALLSTATEPOLL, TIMEVAL_0: 定义不同的时间间隔。&lt;/p&gt;

&lt;p&gt;sState: 当前的无线电状态。&lt;/p&gt;

&lt;p&gt;s_status: 当前的RIL状态。&lt;/p&gt;

&lt;p&gt;s_pfEventCallback: 事件回调函数。&lt;/p&gt;

&lt;p&gt;函数&lt;/p&gt;

&lt;p&gt;is3gpp2: 检查给定的无线电技术是否是3GPP2。&lt;/p&gt;

&lt;p&gt;onRadioPowerOn 和 onSIMReady: 当无线电打开和SIM卡准备好时的回调函数。&lt;/p&gt;

&lt;p&gt;notify_...: 一系列的通知函数，用于在特定事件发生时发送通知。&lt;/p&gt;

&lt;p&gt;pollSIMState: 轮询SIM卡状态。&lt;/p&gt;

&lt;p&gt;requestAntennaPower: 请求天线功率。&lt;/p&gt;

&lt;p&gt;requestRadioPower: 请求设置无线电的开关状态。&lt;/p&gt;

&lt;p&gt;requestShutdown: 请求关闭无线电。&lt;/p&gt;

&lt;p&gt;requestAntenna: 请求特定频段和信道的天线信息。&lt;/p&gt;

&lt;p&gt;requestGSVCNR: 请求GPS信号信息。&lt;/p&gt;

&lt;p&gt;isGnssOn: 检查GNSS（全球导航卫星系统）是否打开。&lt;/p&gt;

&lt;p&gt;requestSetGNSS: 请求设置GNSS的开关状态。&lt;/p&gt;

&lt;p&gt;rsrpToLevel: 将RSRP（参考信号接收功率）转换为信号级别。&lt;/p&gt;

&lt;p&gt;requestNetworkInfo: 请求网络信息。&lt;/p&gt;

&lt;p&gt;requestOperator: 请求运营商信息。&lt;/p&gt;

&lt;p&gt;requestSetupDataCall: 请求设置数据呼叫。&lt;/p&gt;

&lt;p&gt;requestImsi, requestImei, requestIccid, requestEsn: 请求IMSI、IMEI、ICCID和ESN。&lt;/p&gt;

&lt;p&gt;requestIdentification 和 requestModel: 请求设备标识和型号。&lt;/p&gt;

&lt;p&gt;requestBasebandVersion: 请求基带版本。&lt;/p&gt;

&lt;p&gt;requestTimezone: 请求时区信息。&lt;/p&gt;

&lt;p&gt;restartModule: 重启无线电模块。&lt;/p&gt;

&lt;p&gt;currentState: 返回当前无线电状态。&lt;/p&gt;

&lt;p&gt;setRadioState: 设置无线电状态。&lt;/p&gt;

&lt;p&gt;getSIMStatus: 获取SIM卡状态。&lt;/p&gt;

&lt;p&gt;isRadioOn: 检查无线电是否打开。&lt;/p&gt;

&lt;p&gt;onUnsolicited: 处理未经请求的响应。&lt;/p&gt;

&lt;p&gt;onATReaderClosed 和 onATTimeout: 在AT命令读取器关闭或超时时的回调函数。&lt;/p&gt;

&lt;p&gt;mainLoop: RIL的主循环。&lt;/p&gt;

&lt;p&gt;initializeAT: 初始化AT命令。&lt;/p&gt;

&lt;p&gt;initializeCallback: 初始化回调。&lt;/p&gt;

&lt;p&gt;waitForClose: 等待关闭信号。&lt;br&gt;
onSIMStatusChanged 和 onNetworkStatusUpdated:&lt;/p&gt;

&lt;p&gt;这两个函数用于处理SIM状态和网络状态的变更。它们调用相应的通知函数来通知其他系统组件状态的变化。&lt;br&gt;
handleNetworkStatusUpdated 和 handleSimStatusChanged:&lt;/p&gt;

&lt;p&gt;这两个函数用于创建新线程以处理网络和SIM状态的更新。它们确保相关处理不会阻塞AT命令线程。&lt;br&gt;
onUnsolicited:&lt;/p&gt;

&lt;p&gt;当AT命令接口收到未经请求的响应时调用。根据响应的内容，它可能会触发SIM状态或网络状态的更新。&lt;br&gt;
onATReaderClosed 和 onATTimeout:&lt;/p&gt;

&lt;p&gt;这些函数处理AT命令接口的关闭和超时事件。在这些情况下，它们会关闭AT接口，并将RIL状态设置为不可用。&lt;br&gt;
mainLoop:&lt;/p&gt;

&lt;p&gt;RIL的主循环，负责管理AT命令接口的开启和关闭，以及处理相关的初始化和清理工作。&lt;br&gt;
RIL_start:&lt;/p&gt;

&lt;p&gt;启动RIL的主循环。&lt;br&gt;
RIL_sendCommand:&lt;/p&gt;

&lt;p&gt;发送AT命令并获取响应。&lt;br&gt;
RIL_sendEvent:&lt;/p&gt;

&lt;p&gt;发送自定义的AT命令，常用于特定硬件或软件功能的控制。&lt;br&gt;
RIL_requestEventFloatVector、RIL_requestEventStringVector 和 RIL_requestEventIntVector:&lt;/p&gt;

&lt;p&gt;请求特定类型的事件数据（如浮点数、字符串或整数）。&lt;br&gt;
RIL_requestEvent:&lt;/p&gt;

&lt;p&gt;请求一个特定的事件。&lt;br&gt;
RIL_deleteMessage:&lt;/p&gt;

&lt;p&gt;删除存储在SIM卡或设备上的特定短消息。&lt;br&gt;
RIL_readAllMessages:&lt;/p&gt;

&lt;p&gt;读取所有存储的短消息。&lt;br&gt;
RIL_getStatus:&lt;/p&gt;

&lt;p&gt;获取当前RIL的状态。&lt;br&gt;
RIL_getSIMStatus:&lt;/p&gt;

&lt;p&gt;获取当前SIM卡的状态。&lt;br&gt;
RIL_getAntenna、RIL_getCNR 和 RIL_setGNSS:&lt;/p&gt;

&lt;p&gt;获取天线信息、信号信息和控制GNSS模块。&lt;br&gt;
RIL_getNetworkInfo、RIL_getOperator 和 RIL_getSignalStrenth:&lt;/p&gt;

&lt;p&gt;获取网络信息、运营商信息和信号强度。&lt;br&gt;
RIL_getRegistrationState、RIL_getIdentification、RIL_getModel、RIL_getBasebandVersion、RIL_getICCID、RIL_getIMEI、RIL_getIMSI、RIL_getESN 和 RIL_getTimezone:&lt;/p&gt;

&lt;p&gt;获取设备注册状态、标识信息、型号、基带版本、ICCID、IMEI、IMSI、ESN和时区信息。&lt;br&gt;
RIL_restartModule:&lt;/p&gt;

&lt;p&gt;重启无线电模块。&lt;br&gt;
RIL_setEnable:&lt;/p&gt;

&lt;p&gt;启用或禁用RIL。&lt;br&gt;
RIL_deinit 和 RIL_init:&lt;/p&gt;

&lt;p&gt;初始化或反初始化RIL。&lt;/p&gt;

&lt;h1&gt;
  
  
  ipc.cpp
&lt;/h1&gt;

&lt;p&gt;变量&lt;br&gt;
methods:&lt;br&gt;
一个 DbusEvent 类型的数组，定义了不同的方法名和对应的处理函数。这些方法通常被用于与其他服务或应用的IPC通信。&lt;/p&gt;

&lt;p&gt;iface:&lt;br&gt;
DbusInterface 类型的变量，定义了一个接口，其中包含 methods 数组。这个接口用于注册到DBus服务器，以便其他服务或应用可以通过IPC调用这些方法。&lt;/p&gt;

&lt;p&gt;函数&lt;br&gt;
generate_response_json 函数族:&lt;br&gt;
这组重载函数用于生成标准化的JSON格式响应。它们根据不同的情况（如错误代码、数据内容等）来构造响应。&lt;/p&gt;

&lt;p&gt;handle_ril_* 函数族:&lt;br&gt;
一系列以 handle_ril_ 开头的函数，每个函数都处理一个特定的RIL请求。这些函数通常读取请求数据，执行相关操作，然后生成相应的响应数据。&lt;/p&gt;

&lt;p&gt;ipc_start:&lt;br&gt;
启动IPC服务的函数。它调用 dbus_server_start 来注册 iface 接口，允许通过DBus进行IPC通信。&lt;/p&gt;

&lt;p&gt;主要的处理函数和它们的功能&lt;br&gt;
handle_ril_set_id:&lt;br&gt;
设置设备的IMEI和ICCID。&lt;/p&gt;

&lt;p&gt;handle_ril_operator:&lt;br&gt;
获取运营商信息。&lt;/p&gt;

&lt;p&gt;handle_ril_network_info:&lt;br&gt;
获取网络信息。&lt;/p&gt;

&lt;p&gt;handle_ril_hardware_info:&lt;br&gt;
获取硬件信息，如IMEI、型号、基带版本等。&lt;/p&gt;

&lt;p&gt;handle_ril_all_information:&lt;br&gt;
设置或获取所有相关信息。&lt;/p&gt;

&lt;p&gt;handle_ril_enable:&lt;br&gt;
启用或禁用RIL功能。&lt;/p&gt;

&lt;p&gt;handle_ril_get_location:&lt;br&gt;
获取地理位置信息。&lt;/p&gt;

&lt;p&gt;handle_ril_get_camera_config 和 handle_ril_set_camera_config:&lt;br&gt;
获取和设置摄像头配置。&lt;/p&gt;

&lt;p&gt;handle_ril_set_message:&lt;br&gt;
设置消息内容。&lt;/p&gt;

&lt;p&gt;handle_ril_get_facilities_info:&lt;br&gt;
获取设施信息。&lt;/p&gt;

&lt;p&gt;handle_ril_get_device_info:&lt;br&gt;
获取设备信息。&lt;/p&gt;

&lt;p&gt;handle_ril_send_at_command:&lt;br&gt;
发送AT命令。&lt;/p&gt;

&lt;p&gt;handle_ril_set_ntp_server:&lt;br&gt;
设置NTP服务器。&lt;/p&gt;

&lt;p&gt;handle_ril_set_udisk_enable:&lt;br&gt;
启用或禁用U盘功能。&lt;/p&gt;

&lt;p&gt;handle_ril_set_setup_fota_enable:&lt;br&gt;
启用或禁用FOTA功能。&lt;/p&gt;

&lt;p&gt;handle_ril_notify_job_finished:&lt;br&gt;
通知任务完成。&lt;/p&gt;

&lt;p&gt;handle_ril_set_power_off_mode 和 handle_ril_get_power_on_mode:&lt;br&gt;
设置或获取电源开关模式。&lt;/p&gt;

&lt;p&gt;handle_ril_get_mcu_version:&lt;br&gt;
获取MCU版本。&lt;/p&gt;

&lt;p&gt;handle_ril_get_versions:&lt;br&gt;
获取不同组件的版本信息。&lt;/p&gt;

&lt;p&gt;handle_ril_get_hardware_id:&lt;br&gt;
获取硬件ID。&lt;/p&gt;

&lt;p&gt;handle_ril_set_time_zone:&lt;br&gt;
设置时区。&lt;/p&gt;

&lt;p&gt;handle_ril_notify_time_changed:&lt;br&gt;
通知时间更改。&lt;/p&gt;

&lt;p&gt;handle_ril_set_led_state:&lt;br&gt;
设置LED状态。&lt;/p&gt;

&lt;p&gt;handle_ril_get_sdcard_level:&lt;br&gt;
获取SD卡水平。&lt;/p&gt;

&lt;p&gt;handle_ril_start_fota:&lt;br&gt;
开始FOTA更新。&lt;/p&gt;

&lt;p&gt;handle_ril_esim_profile_* 函数族:&lt;br&gt;
一系列处理eSIM配置文件的函数。&lt;/p&gt;

&lt;p&gt;handle_ril_dump:&lt;br&gt;
打印系统状态信息。&lt;/p&gt;

&lt;p&gt;handle_ril_reset:&lt;br&gt;
执行系统重置。&lt;/p&gt;

&lt;p&gt;handle_ril_enter_test_mode:&lt;br&gt;
进入测试模式。&lt;/p&gt;

&lt;p&gt;handle_ril_set_serial_address:&lt;br&gt;
设置序列号和地址。&lt;/p&gt;

&lt;p&gt;handle_ril_get_barcode:&lt;br&gt;
获取条形码。&lt;/p&gt;

&lt;p&gt;handle_ril_get_serial_address:&lt;br&gt;
获取序列号和地址。&lt;/p&gt;

&lt;p&gt;handle_ril_set_fota_server 和 handle_ril_get_fota_server:&lt;br&gt;
设置或获取FOTA服务器信息。&lt;/p&gt;

&lt;p&gt;handle_ril_sdcard_state_changed:&lt;br&gt;
通知SD卡状态变更。&lt;/p&gt;

</description>
    </item>
    <item>
      <title>代码大全随笔</title>
      <dc:creator>Ariston</dc:creator>
      <pubDate>Mon, 22 Jan 2024 18:06:11 +0000</pubDate>
      <link>https://dev.to/weltlgit/dai-ma-da-quan-sui-bi-54mk</link>
      <guid>https://dev.to/weltlgit/dai-ma-da-quan-sui-bi-54mk</guid>
      <description>&lt;p&gt;本书特色：检查表？（目前还不太清楚是什么东西），例程（超脱了语言的束缚），强调了创建活动的重要性，（详细代码、编码、调试、单元测试，貌似是这样，也可能不是），&lt;/p&gt;

&lt;h1&gt;
  
  
  第一章 欢迎进入软件创建世界
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1.1 什么是软件创建
&lt;/h2&gt;

&lt;p&gt;这项工作的主要方面：&lt;br&gt;
1.问题定义&lt;br&gt;
2.需求分析&lt;br&gt;
3.实现计划&lt;br&gt;
4.总体设计&lt;br&gt;
5.详细设计&lt;br&gt;
6.创建及实现&lt;br&gt;
7.系统集成&lt;br&gt;
8.单元测试&lt;br&gt;
9.系统测试&lt;br&gt;
10.校正性的维护&lt;br&gt;
11.功能强化&lt;/p&gt;

&lt;p&gt;创建活动主要指编码和调试过程，亦包括详细设计和测试中的某些工作。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2wu911ir75iooydhvbb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2wu911ir75iooydhvbb.png" alt="Image description" width="800" height="644"&gt;&lt;/a&gt;&lt;br&gt;
创建活动包括了：编写源代码、代码审查和重构、单元测试和验证代码的正确性、集成不同的代码模块、调优和优化性能、编写文档和注释以提高代码的可读性和可维护性。&lt;br&gt;
创建活动在开发软件中有着及其重要的地位、主要精力用于创建活动，可以极大地提高程序员的生产效率。 &lt;br&gt;
创建活动是总体设计和系统测试之间承上启下的工作。&lt;br&gt;
对于创建活动的其他称谓有：实现、编程等。&lt;/p&gt;

&lt;h1&gt;
  
  
  第二章 利用隐喻对编程进行更深刻的理解
&lt;/h1&gt;

&lt;p&gt;好的隐喻就是，软件开发之创建活动和建造建筑很像。&lt;br&gt;
智能工具箱隐喻也是很不错的。&lt;br&gt;
对于一个很大的软件工程来说，比如750000行代码的系统，可能需要多大600页的功能定义文件，所以说&lt;strong&gt;计划&lt;/strong&gt;对于大型软件要在更高的层次进行。&lt;/p&gt;

&lt;h1&gt;
  
  
  第三章 软件创建的先决条件
&lt;/h1&gt;

&lt;h2&gt;
  
  
  3.1 先决条件的重要性
&lt;/h2&gt;

&lt;p&gt;测试不是控制软件高质量的最重要的部分，只是全部质量控制策略的一部分。有很多错误要在创建工作开始之前就清除掉。&lt;/p&gt;

&lt;p&gt;如果我们在创建中间强调质量，那么我们强调的是创建活动。&lt;br&gt;
如果我们在计划开始强调质量，意味着我们要设计一款高质量的产品，比如如果我们一开始设计的是菲亚特，那么在创建中间强调质量，这点如果做的再好，也无法做成劳斯莱斯。&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1.1 造成准备不足的原因
&lt;/h3&gt;

&lt;p&gt;对于我来说，那肯定就是项目赶得急，时间不足，就无法把控质量。&lt;/p&gt;

&lt;p&gt;在创建工作之前一定要进行充分的准备工作&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1.2 在创建工作之前必须做准备工作的论据
&lt;/h3&gt;

&lt;h4&gt;
  
  
  求助于逻辑推理
&lt;/h4&gt;

&lt;p&gt;从管理人员的角度来看，计划是确定一个项目所需要的时间、人力、物力和财力。从技术人员的观点看，计划是指弄清楚你想要干什么，以免做出错误的工作而徒耗精力和钱财。如果我们一开始没做好准备工作，那么可能方向歪了，浪费很多&lt;/p&gt;

&lt;h4&gt;
  
  
  求助于类比
&lt;/h4&gt;

&lt;p&gt;建房子之前画好建筑图和蓝图；圣诞树立起来之后，我们才装饰；&lt;/p&gt;

&lt;p&gt;程序员处于软件开发食物链的最后一环。结构设计吃掉需求分析；详细设计者以结构设计者为食，而他自己又成为编码者的食物。比较软件食物链和真正的食物链，我们会发现如下事实，在一个正常的生态系统中，海鸥以沙丁鱼为食，沙丁鱼吃鲜鱼，鲜鱼吃水虱，其结果会形成一个正常的食物链。在编程工作中，如果软件食物链的每一级都可以吃到健康的食物，其结果是由一群快乐的程序员写出的正确代&lt;br&gt;
码。在程序设计中, 如果需求定义遭受了污染，那么这又会影响结构设计，而这将最终影响创建活动。这将导致程序员们脾气暴躁而营养不良，同时生产出遭受严重污染而充满缺陷的软件。&lt;/p&gt;

&lt;p&gt;一次完成是最好的选择，不必要的修改比较昂贵，在项目初期进行更改，比创建和维护阶段更改相比，成本低50-100倍数。一旦引入错误，就尽早发现并且消除，（如同屎山的危害）&lt;/p&gt;

&lt;h2&gt;
  
  
  3.2 问题定义先决条件
&lt;/h2&gt;

&lt;p&gt;问题定义应该从用户的角度出发，用用户的语言进行定义。&lt;/p&gt;

&lt;h2&gt;
  
  
  3.3 需求分析先决条件
&lt;/h2&gt;

&lt;p&gt;需求是由用户决定系统的功能，需求定义可以避免程序员之间的争议，可以对系统作的改动最小。我们要对需求进行分析，看看有没有错误，如果有错误的话此时改动成本最小。&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3.2 需求稳定的神话
&lt;/h3&gt;

&lt;p&gt;但是很多时候需求都是变动的，所以我们要一直随着需求变&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3.3 在创建阶段如何对付需求变化
&lt;/h3&gt;

&lt;p&gt;如果需求分析做的不好，马上停止，重新返回到需求分析阶段，这是很有必要的。&lt;/p&gt;

&lt;p&gt;让每个人都知道变化需求所付出的代价。&lt;br&gt;
确立审查更改需求的正式委员会，有一套控制更改的正式过程。&lt;/p&gt;

&lt;p&gt;用开发的方法来容纳变动&lt;br&gt;
先原型化开发，然后渐进开发，&lt;/p&gt;

&lt;p&gt;放弃项目&lt;br&gt;
如果项目比较奇怪，那就直接放弃砍掉&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3.4 检查表
&lt;/h3&gt;

&lt;p&gt;书中的这个表中的每一个问题并非都适用，比如一些非正式项目，但是如果正在从事一个大型的正式项目，最好还是仔细考虑每一个问题。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8zpwqw44uugzcamr8pf9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8zpwqw44uugzcamr8pf9.png" alt="Image description" width="608" height="754"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3.4 结构设计先决条件
&lt;/h2&gt;

&lt;p&gt;较高层级的软件设计，是详细设计的框架，和需求定义一样，变动结构设计的成本也是昂贵的，书中的这部分主要是&lt;strong&gt;如何确定一个现存结构的质量&lt;/strong&gt;。&lt;/p&gt;

&lt;h3&gt;
  
  
  3.4.1 典型的结构要素
&lt;/h3&gt;

&lt;h4&gt;
  
  
  程序的组织形式
&lt;/h4&gt;

&lt;p&gt;要是模块化的，我们要清楚的知道自己所开发的这一个模块对系统有什么贡献，一个模块并不是子程序，而是能完成某一高级功能的子程序的组合。每一个模块做什么应当作出明确的定义。一个模块应该只完成一项任务。如果两个模块覆盖了同一项功能，那么他们应该是互补的而不是冲突的。对于模块间的关系也应该明确定义，哪些模块可以被哪些模块调用，哪些不能调用。&lt;/p&gt;

&lt;h4&gt;
  
  
  变动策略
&lt;/h4&gt;

&lt;p&gt;由于在创建过程中作出变动是不可避免地，所以结构设计应该能清晰的描述系统应付变动的策略。&lt;br&gt;
建议使用表驱动技术而不是硬编码技术。这样可以不必重新编译就能对程序作出调整。&lt;/p&gt;

&lt;h4&gt;
  
  
  购买而不是建造的决定
&lt;/h4&gt;

&lt;p&gt;用老程序，用别人写好的，开发成本是极其昂贵的&lt;/p&gt;

&lt;h4&gt;
  
  
  主要的数据结构
&lt;/h4&gt;

&lt;p&gt;1.数据结构很重要，当我们更换数据结构，就一定要解释为什么它优于其他类型的数据结构&lt;br&gt;
2.结构设计应详细说明使用的主要文件、表和数据结构。包括组织形式和内容。&lt;br&gt;
3.不应允许多个模块直接访问相同的数据结构，保证信息隐藏，降低系统复杂性提高可维护性。&lt;br&gt;
4.如果程序使用数据库，结构设计中应规定数据库的组织形式和内容&lt;br&gt;
5.每一个输入的数据都应该有相应的输出&lt;/p&gt;

&lt;h4&gt;
  
  
  关键算法
&lt;/h4&gt;

&lt;p&gt;对于关键算法的选择和数据结构一样，也要指出原因是什么&lt;/p&gt;

&lt;h4&gt;
  
  
  主要对象
&lt;/h4&gt;

&lt;p&gt;对于面向对象的系统中，指出对象之间的责任并指出对象之间是如何相互作用的。包括对于排序层次、状态转换和对象一致性的描述。&lt;/p&gt;

&lt;h4&gt;
  
  
  通用功能
&lt;/h4&gt;

&lt;p&gt;有些功能是几乎所有软件都应该有的通用功能&lt;/p&gt;

&lt;h5&gt;
  
  
  用户界面
&lt;/h5&gt;

&lt;p&gt;应当在在结构设计中作出规定，把这部分直接模块化，这样新的代替旧的的时候，就不影响处理和输出的部分，而且要做好批处理接口，这样的话测试起来比较容易，这部分可以写一本书，但本书中未涉及。&lt;/p&gt;

&lt;h5&gt;
  
  
  输入/输出
&lt;/h5&gt;

&lt;p&gt;通过在不同的层次上进行错误检查，可以更有效地识别和处理数据问题，从而提高系统的健壮性和数据的准确性。&lt;/p&gt;

&lt;h5&gt;
  
  
  内存管理
&lt;/h5&gt;

&lt;h5&gt;
  
  
  字符串存储
&lt;/h5&gt;

&lt;p&gt;在交互式系统中，字符串占用的内存，有时候可能是很大的，所以有些时候，我们要考虑字符串是应该放在代码、还是文件中，结构涉及应指明采用哪种方法&lt;/p&gt;

&lt;h4&gt;
  
  
  错误处理
&lt;/h4&gt;

&lt;p&gt;是当代CS中最棘手的问题，有90%代码是为了应付例外的错误编写的。&lt;br&gt;
错误处理是纠正还是测试错误？如果是纠正，可以尝试从错误状态下回复，但总归要提醒用户。&lt;br&gt;
错误是主动还是被动的?系统可以积极预防，比如检测用户的输入是否合法。&lt;br&gt;
也要有一套处理错误信息的约定。&lt;br&gt;
哪一个层次处理错误也要着手考虑，是在发现的地方处理，还是交给错误处理子程序处理，还是交给更高层次子程序处理。&lt;br&gt;
需要分配是各自的模块自己检验自己的数据，还是有一个专门的模块负责，分工明确能效率更高。&lt;/p&gt;

&lt;h4&gt;
  
  
  坚固性
&lt;/h4&gt;

&lt;p&gt;指发现错误后，一个系统继续运行的能力，&lt;/p&gt;

&lt;h5&gt;
  
  
  裕度设计
&lt;/h5&gt;

&lt;p&gt;裕度：系统设计中故意加入的额外能力或资源，用于保证在出现意外情况或超出正常操作范围时系统仍能正常运行。&lt;br&gt;
软件坚固是由最薄弱一环决定的，所以裕度级一定要弄清楚。&lt;/p&gt;

&lt;h5&gt;
  
  
  断言
&lt;/h5&gt;

&lt;h5&gt;
  
  
  容错性
&lt;/h5&gt;

&lt;h5&gt;
  
  
  性能
&lt;/h5&gt;

&lt;p&gt;包括速度和内存使用&lt;/p&gt;

&lt;h4&gt;
  
  
  通用的设计质量设计准则
&lt;/h4&gt;

&lt;p&gt;好的结构设计的特征包括对于模块的讨论，每个模块中隐含的信息，选用和不选用某方案的原因是什么。&lt;br&gt;
一个以可变性为首要目标的结构设计可能与一个以性能为首&lt;br&gt;
要目标的结构设计差之千里，虽然二者的功能可能是完全一样的。&lt;br&gt;
结构设计的每一次变动都应该与总体设计概念相符。&lt;br&gt;
设计者不能以牺牲某一部分为代价来重视另一部分。&lt;/p&gt;

&lt;h3&gt;
  
  
  3.4.2 检查表
&lt;/h3&gt;

&lt;h4&gt;
  
  
  结构设计
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckyizijbf1e1jj8ovu42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckyizijbf1e1jj8ovu42.png" alt="Image description" width="595" height="57"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8f9jyjc7u0e7axrvtmjq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8f9jyjc7u0e7axrvtmjq.png" alt="Image description" width="593" height="661"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3.5 选择编程语言先决条件
&lt;/h2&gt;

&lt;h1&gt;
  
  
  3.5.1语言描述
&lt;/h1&gt;

&lt;h2&gt;
  
  
  3.6 编程约定
&lt;/h2&gt;

&lt;p&gt;低层次实现和结构设计的概念完整性一致。约定说明一定要详细，使得编程中无法对其改动。&lt;/p&gt;

&lt;h2&gt;
  
  
  3.7 应花在先决条件上的时间
&lt;/h2&gt;

&lt;p&gt;大约应占20%-30%，不包括详细设计的时间，详细设计是创建活动的一部分。&lt;br&gt;
如果是正式项目，需求不稳定，我们要跟需求分析员解决定义需求问题，让需求定义更适合项目需要。&lt;/p&gt;

</description>
    </item>
    <item>
      <title>网络扫描</title>
      <dc:creator>Ariston</dc:creator>
      <pubDate>Mon, 22 Jan 2024 11:58:28 +0000</pubDate>
      <link>https://dev.to/weltlgit/wang-luo-sao-miao-35e5</link>
      <guid>https://dev.to/weltlgit/wang-luo-sao-miao-35e5</guid>
      <description>&lt;h1&gt;
  
  
  一、名词解释部分、不懂之处
&lt;/h1&gt;

&lt;p&gt;1.后端代码：由哪部分来实现的？&lt;br&gt;
2.管理员面板：&lt;br&gt;
3.SuperAPI：&lt;br&gt;
4.什么是 a more limited extend the end user.&lt;br&gt;
5.对于camera network status and availability中的两部分数据都分别要实现哪些？&lt;br&gt;
6.对于camera network status and availability什么是网络覆盖图？&lt;br&gt;
7.对于requirements of the data ...中的celluar模块是哪个？esim卡那部分吗？&lt;br&gt;
8.AT命令大全在哪？对于ROD中的算法说的是什么算法？我们需要提供吗？&lt;br&gt;
9、对于ROD中的在某些情况下要求celluar离线，是什么情况，并且这里说了要在特定的时间在线，这个特定的事件是什么时候？&lt;br&gt;
10.ROD中说的可能影响设备（附着或连接）到LTE的部分，其中附着指的是设备在网络中注册并获得服务的过程（详见gptAtel）。&lt;/p&gt;

&lt;h1&gt;
  
  
  二、需求分析
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1.需求目的:
&lt;/h2&gt;

&lt;p&gt;提供一个网络扫描功能为用户还有服务器提供网络信息&lt;/p&gt;

&lt;h2&gt;
  
  
  2.需求具体功能
&lt;/h2&gt;

&lt;p&gt;(1)确保摄像头网络可用，目前打算的&lt;strong&gt;实现&lt;/strong&gt; ：放到文件(供后端或者admin panel)或者打印到终端中，这个还要看后续的实现&lt;br&gt;
(2)扫描服务小区（serving cell）的网络条件还有该地区的网络运营商来访问数据&lt;br&gt;
(3)所有camped或attach的数据都需要被记录。&lt;/p&gt;

&lt;h3&gt;
  
  
  (4)触发这一功能并且把数据发到服务器的方式：
&lt;/h3&gt;

&lt;p&gt;1.用户或者服务器可以触发扫描，扫描MNO网络和RF信号。&lt;br&gt;
2.摄像头移动了距离？（那么这个移动的距离，是什么东西？应当由什么来触发？）会再次触发扫描。需求中说这部分由后端来处理，那么后端负责触发？摄像头移动距离，然后给后端？后端来触发这个扫描？&lt;br&gt;
3.两种处理和存储网络扫描数据的方法：1.原样把数据以文本格式储存，2.只有特定的响应结果？（这个特定的响应结果是什么东西？），谁把这部分上传到S3？（如果是我的话，那么这部分代码在哪？）&lt;/p&gt;

&lt;h3&gt;
  
  
  (5)SMS命令发送网络扫描信息
&lt;/h3&gt;

&lt;p&gt;这里面说的Daily Report process是什么？&lt;br&gt;
1.谁发SMS命令？&lt;br&gt;
2.SMS命令的三种形式，&lt;br&gt;
SR12*1$ 收集/执行网络扫描并发送&lt;br&gt;
SR12*2$ 只收集网络扫描数据（不发送）&lt;br&gt;
SR12*3$ 发送已经之前收集的网络扫描数据&lt;br&gt;
3.Xpro和XGen2分别是哪两种设备？&lt;br&gt;
按5s之后触发&lt;br&gt;
相机能够发送&lt;br&gt;
这里面只是说把这个扫描结果发送到FTP服务器，那么就只是发到FTP服务器就ok？&lt;/p&gt;

&lt;h3&gt;
  
  
  (6)网络扫描功能的限制和考虑：
&lt;/h3&gt;

&lt;p&gt;1.只检查4GLET网络，一条AT命令，&lt;strong&gt;那么到底是AT命令来触发，还是SMS命令来触发？&lt;/strong&gt;&lt;br&gt;
2.5min如果还是空，那么网络扫描超时，然后相机关闭（当相机处于开机状态时）或重启。无需更新网络扫描文件&lt;br&gt;
3.网络扫描文件最多50条，如果超出50条，那么会从一条开始删除，&lt;br&gt;
4.当网络扫描文件被发送到服务器时，相机不会对其他按钮操作作出反应。&lt;/p&gt;

&lt;h3&gt;
  
  
  (7)网络扫描的触发
&lt;/h3&gt;

&lt;p&gt;1.用户启动：&lt;br&gt;
通过按键或MMI界面来手动触发网络扫描，用户会被通知（也就是给个回复这样子），一次可能要几分钟&lt;br&gt;
扫描是为了在手机APP中获得详细的网络信息。&lt;br&gt;
用户请求RF，扫描完成后，结果发送到S3中，文件名格式按照文档中的说明&lt;br&gt;
2.后端启动/Tactacam网络&lt;br&gt;
后端可以用MQTT协议发起，（可能要自己通过MQTT来触发）&lt;br&gt;
当后端或者Tactacam发起时，有两个选项：&lt;br&gt;
1.app接受命令，并初始化扫描，当扫描完成时把数据发送到服务器&lt;br&gt;
2.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>unix高级编程之信号</title>
      <dc:creator>Ariston</dc:creator>
      <pubDate>Wed, 17 Jan 2024 00:46:06 +0000</pubDate>
      <link>https://dev.to/weltlgit/unixgao-ji-bian-cheng-zhi-xin-hao-ofn</link>
      <guid>https://dev.to/weltlgit/unixgao-ji-bian-cheng-zhi-xin-hao-ofn</guid>
      <description>&lt;h1&gt;
  
  
  一、信号提出的背景
&lt;/h1&gt;

&lt;p&gt;信号在unix早期版本就已经提供，用于进程间通信，他们提供了一种方式，使得操作系统能够&lt;strong&gt;中断&lt;/strong&gt;进程的执行，以通知它发生了某个时间。这个机制最初是为了处理不同的异步事件。&lt;/p&gt;

&lt;h1&gt;
  
  
  二、信号概念
&lt;/h1&gt;

&lt;p&gt;每个信号都有一个名字这，些名字都以SIG开头。在头文件或中，都是正整数常量。&lt;br&gt;
信号由内核产生。&lt;br&gt;
当某种信号出现时，我们可以采用以下三种方式：&lt;br&gt;
1.忽略&lt;br&gt;
2.捕捉信号（不能捕捉SIGKILL和SIGSTOP）&lt;br&gt;
3.执行系统默认动作，对于每一种系统默认动作，大多数都是终止该进程。&lt;br&gt;
对于有些信号，默认动作是终止+core，其中core文件复制了该进程的内存映像，core文件可以用来检查进程终止时的状态。&lt;br&gt;
不产生core文件的5个条件，详见书中252页。&lt;/p&gt;

&lt;p&gt;一些扫了一眼看上去比较重要的信号：&lt;br&gt;
SIGPIPE：在管道终止时写管道会产生此信号。当类型为SOCK_STREAM的套接字不再连接，进程写该套接字也会产生此信号。&lt;br&gt;
SIGKILL、SIGSTOP：两大不能忽视和捕捉的信号。第一个杀死一个进程，第二个则是挂起一个进程。&lt;br&gt;
SIGTERM：和SIGKILL类似，也是用于中止一个进程的，区别在于该信号能被捕获，让程序有机会在退出之前做好清理工作。&lt;br&gt;
SIGTTIN：后台进程组进程试图读取控制终端会产生此信号。有两种特殊情况，1.写进程忽略或阻塞此信号。2.写进程属于孤儿进程组，直接返回出错。&lt;/p&gt;

&lt;p&gt;对于信号处理程序，那自然是越简单越快速越好。&lt;/p&gt;
&lt;h1&gt;
  
  
  来自man
&lt;/h1&gt;
&lt;h2&gt;
  
  
  1.signal
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="nf"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sighandler_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;sighandler_t&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;signum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sighandler_t&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;对于捕捉到的信号有三个动作，分别是忽略、系统默认和捕捉。&lt;br&gt;
当handler的值是&lt;br&gt;
SIG_IGN忽略此信号&lt;br&gt;
SIG_DFL系统默认此信号&lt;br&gt;
自定义函数，指定函数地址时，称此函数为signal handler或signal-catching function&lt;br&gt;
对于signal的返回值，是上一个信号处理函数的地址。我们不关心这个，所以我们不接收signal的返回。&lt;br&gt;
书中10-2的代码，其中kill并不是杀死进程，而是发送一个信号给一个进程或进程组。&lt;br&gt;
当我们用exec开启进程，如果原本对于信号的处理是忽略，那么还是忽略，此外其他的全部都是变成默认。&lt;br&gt;
用fork则保留父进程的信号处理方式。&lt;/p&gt;
&lt;h2&gt;
  
  
  2.不可靠的信号
&lt;/h2&gt;

&lt;p&gt;这种老版本会有时间窗口问题，也就是在处理第一个信号时，第二个信号也过来了，那么对第二个信号的处理会采取系统默认的行为，（在 Unix 中，信号处理函数一旦被调用，除非重新设置，否则系统会将信号的处理方式重置为默认。这意味着如果在处理函数执行期间再次收到相同的信号，系统会采取该信号的默认行动，如终止程序。）后面会有更现代的做法。&lt;/p&gt;
&lt;h2&gt;
  
  
  3.中断的系统调用
&lt;/h2&gt;

&lt;p&gt;有些系统调用捕捉到了信号中断后会重新启动，比如ioctl、read、readv、write、writev、wait和waitpid。前5个函数只有在对低速设备进行操作时才会被信号中断，而wait和waitpid捕捉到信号时总是被中断。但是我们有时候不希望这些被中断后重新启动。&lt;/p&gt;

&lt;p&gt;注意：在这里我们要区分系统调用和函数，被中断的是内核中执行系统调用而不是函数，&lt;/p&gt;

&lt;p&gt;低速系统调用，它们需要等待一些外部事件发生，但是可能他们永远不会发生。&lt;/p&gt;
&lt;h2&gt;
  
  
  4.可重入函数
&lt;/h2&gt;

&lt;p&gt;可以被中断并安全地被另一个线程调用的函数&lt;br&gt;
成为可重入函数要满足如下几个条件：&lt;br&gt;
1.不使用静态或全局数据：可重入函数不能依赖存储在全局或静态变量中的数据，除非这些数据是常量。依赖全局或静态数据会使函数在并发环境中的行为变得不可预测。&lt;/p&gt;

&lt;p&gt;2.不修改自己的代码：也就是说，函数不能包含自修改代码。&lt;/p&gt;

&lt;p&gt;3.不调用不可重入的函数：可重入函数在执行过程中不能调用其他不可重入的函数，因为那将使整个函数调用链不可重入。&lt;/p&gt;

&lt;p&gt;4.使用局部变量：可重入函数应该只操作传入的参数和局部变量。因为局部变量通常存储在堆栈上，每次函数调用都会得到自己的变量副本。&lt;/p&gt;
&lt;h2&gt;
  
  
  5.SIGCLD语义
&lt;/h2&gt;

&lt;p&gt;SIGCLD是进程的子进程状态发生改变时，进程收到的信号，信号SIGCLD或SIGCHLD的默认行为通常是被忽略，这意味着默认情况下父进程不会对它做出任何反应。但是，父进程可以通过编写信号处理函数来捕获这个信号，并进行相应的处理，如调用wait()系列函数来获取子进程的终止状态并清理资源。这样做可以防止子进程成为僵尸进程。&lt;br&gt;
例如，父进程可能会这样设置一个信号处理函数来响应SIGCHLD信号：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/wait.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;signal.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;child_exit_signal_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;pid_t&lt;/span&gt; &lt;span class="n"&gt;child_pid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// 当捕获到SIGCHLD信号时，调用waitpid()来处理子进程的退出&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;child_pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;waitpid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WNOHANG&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WIFEXITED&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Child process %d exited with status %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;child_pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WEXITSTATUS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WIFSIGNALED&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Child process %d was terminated by signal %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;child_pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WTERMSIG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;sigaction&lt;/span&gt; &lt;span class="n"&gt;sa&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;sa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sa_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;child_exit_signal_handler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;sigemptyset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sa_mask&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;sa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sa_flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SA_RESTART&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;SA_NOCLDSTOP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sigaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SIGCHLD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sigaction"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 这里可以创建子进程和其他逻辑&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6.可靠信号术语和语义
&lt;/h2&gt;

&lt;h3&gt;
  
  
  早期的Unix信号处理限制：
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1.不排队：早期Unix信号不会排队。如果两个相同类型的信号几乎同时发生，只有一个会被递送；因此，可能丢失信号。
&lt;/h4&gt;

&lt;h4&gt;
  
  
  2.不可阻塞：某些信号不能被阻塞，这意味着程序无法暂时忽略这些信号，即使它们在不便的时刻到达。
&lt;/h4&gt;

&lt;h4&gt;
  
  
  3.默认行为限制：对于大多数信号，进程只能选择接收默认行为（通常是终止）或忽略信号，而不能指定一个自定义的处理函数。
&lt;/h4&gt;

&lt;h3&gt;
  
  
  可靠信号的特点：
&lt;/h3&gt;

&lt;p&gt;1.可阻塞：几乎所有的信号都可以被阻塞。如果一个信号被阻塞，那么产生的信号将不会立即递送给进程，直到该信号被解除阻塞。这允许程序控制信号的处理时间，防止在关键代码执行期间被中断。&lt;br&gt;
2.排队支持：虽然标准的Unix信号机制本身不支持排队，POSIX标准引入的实时信号提供了信号排队的功能。这意味着，如果有多个实时信号被发送到进程，它们将会被逐一递送，减少了信号丢失的风险。&lt;br&gt;
3.信号处理函数：程序可以为大多数信号指定自定义的处理函数（信号处理程序），这允许执行比默认行为更复杂的操作。&lt;/p&gt;
&lt;h3&gt;
  
  
  术语和语义
&lt;/h3&gt;

&lt;p&gt;可靠信号是指不会丢失、可以被适当阻塞并处理的信号机制。&lt;br&gt;
语义：指信号处理的行为和信号系统的设计原则，包括如何递送、阻塞和处理信号。&lt;br&gt;
在信号产生和信号送达的这个时间内，信号是未决的pending。&lt;/p&gt;
&lt;h2&gt;
  
  
  kill和raise
&lt;/h2&gt;

&lt;p&gt;kill将信号发给进程或进程组。&lt;br&gt;
raise将信号发给自身&lt;/p&gt;
&lt;h2&gt;
  
  
  alarm和pause
&lt;/h2&gt;

&lt;p&gt;alarm为当前进程设置一个计时器，计时器到期时，操作系统向进程发送SIGALRM信号，如果进程没有捕获或者忽略这个信号，进程将执行默认的信号处理动作，即停止。&lt;br&gt;
alarm函数常用于限制某操作的执行时间。比如在网络编程中，可能希望限制连接操作的时间，防止程序因等待响应而无限期挂起。&lt;br&gt;
alarm的返回值是之前设置的闹钟的剩余的秒数。&lt;br&gt;
当你在代码中连续两次调用alarm函数时，第二次调用会取消前一次alarm调用所设置的定时器，并替换为新的定时器。&lt;/p&gt;

&lt;p&gt;pause函数使调用进程挂起直到捕获一个信号。&lt;br&gt;
pause不关心返回值，因为它一直在等待某个信号到来，总是返回-1&lt;/p&gt;

&lt;p&gt;二者搭配使用，示例如下&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;signal.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;handle_alarm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Alarm went off!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// 在这里可以执行定时器到期后需要完成的任务&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 设置SIGALRM的处理函数&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SIGALRM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handle_alarm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;SIG_ERR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Signal handler setting failed"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Setting a 5-second alarm...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;alarm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 设置定时器为5秒&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pausing until the alarm goes off...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 等待信号，挂起程序&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Doing some work after the alarm...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// 定时器到期后需要执行的代码&lt;/span&gt;
    &lt;span class="c1"&gt;// 例如：清理工作、准备下一个定时器、或其他逻辑&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;示例代码展示错误的sleepl，简介展示了alarm和pause这两者操作有时需要原子性的必要&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;signal.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sig_alrm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;signo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;sleep1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SIGALRM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sig_alrm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;SIG_ERR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;alarm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alarm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"before sleep&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;sleep1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"after sleep&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;这里面的问题就在于，如果在pasue没被调用起来的时候，SIGALRM信号到达，alarm返回了，这是就会造成该进程一直处于挂起状态。&lt;br&gt;
还有就是如果在sleepl之前alarm就被调用了，那么后面的alarm就会擦出之前的alarm导致前面的alarm永远不会接收到SIGALRM信号。&lt;br&gt;
还有就是如果其他的函数需要用alarm做一些操作，但是这里用的signal(SIGALRM, sig_alrm)就把这个设置为空了，别的函数就不能在捕捉到SIGALRM信号时做一些操作了。&lt;/p&gt;
&lt;h2&gt;
  
  
  信号集
&lt;/h2&gt;

&lt;p&gt;表示一个或多个信号的集合。&lt;br&gt;
早期的信号数量少，少于一个整型所包含的位数，但是后来多起来了，就不能再用普通的整型来表示信号了，&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;sigemptyset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sigset_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;sigfillset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sigset_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;sigaddset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sigset_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;signo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;sigdelset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sigset_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;signo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//成功返回0出错返回-1&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;sigismember&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;sigset_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;signo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  函数sigprocmask
&lt;/h2&gt;

&lt;p&gt;是一个信号管理函数，用于检查和更改进程的信号屏蔽字，信号屏蔽字是一个信号集，指示了哪些信号被阻塞不能被递送给进程。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;sigprocmask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;how&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;sigset_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sigset_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;oldset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  函数sigpending
&lt;/h2&gt;

&lt;p&gt;用于检查当前进程的挂起信号集，挂起信号集是已被发送给进程但还未被处理的信号，&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;signal.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;sigpending&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sigset_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  函数sigaction
&lt;/h2&gt;

&lt;p&gt;用来检查或修改与指定信号相关联的处理动作，允许程序更精确地控制信号的各种行为。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;signal.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;sigaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;signum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;sigaction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;act&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;sigaction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;oldact&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;示例代码如下&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;signal.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sigint_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Caught signal %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;sigaction&lt;/span&gt; &lt;span class="n"&gt;act&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;act&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sa_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sigint_handler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;sigemptyset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;act&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sa_mask&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;act&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sa_flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sigaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SIGINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;act&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sigaction"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 等待信号&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(;;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 使进程暂停，直到接收到信号&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;signaction&lt;/span&gt;&lt;span class="err"&gt;的内部如下：&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>socket初步学习</title>
      <dc:creator>Ariston</dc:creator>
      <pubDate>Fri, 12 Jan 2024 01:31:31 +0000</pubDate>
      <link>https://dev.to/weltlgit/socketchu-bu-xue-xi-1nli</link>
      <guid>https://dev.to/weltlgit/socketchu-bu-xue-xi-1nli</guid>
      <description>&lt;h1&gt;
  
  
  1.Synopsis
&lt;/h1&gt;

&lt;p&gt;包含头文件&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/socket.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;//function signature&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;socket&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;j信）。那么这个domain是什么呢？比如说AF_INET对应的就是IPv4,地址是这样的192.168.1.1，然后AF_INET6的地址形式2001:0db8:85a3:0000:0000:8a2e:0370:7334，AF_UNIX 或 AF_LOCAL为/tmp/socket。不同的domain对应不同的网络协议和通信方式。&lt;br&gt;
对于type，我们一般会用的形式如下SOCK_STREAM（TCP）、SOCK_DGRAM（UDP）、SOCK_RAW（用于网络应用程序的开发和测试）、SOCK_SEQPACKET（和TCP的区别就是保留了数据边界）、SOCK_PACKET（用于特定的网络分析和配置）。SOCK_NONBLOCK和SOCK_CLOEXEC，分别是非阻塞模式和执行关闭模式，第一个如果一个操作不能立即完成，直接返回错误；第二个设置一个套接字，然后这个套接字是如果该进程中使用了exec系列函数，那么这个套接字直接关闭，这两个type可以与传统的type or使用。&lt;br&gt;
type是SOCK_SEQPACKET时，可以认为每个读操作都是原子的，即使在面对信号中断时也是如此。&lt;/p&gt;

&lt;p&gt;/&lt;em&gt;这里面先小提一嘴exec，exec会开一个新程序，这个新程序会替换当前进程的映像、数据、堆和栈等部分为新的程序。pid、文件描述符什么的不变，总而言之，开一个新进程替换了原来的程序，&lt;br&gt;
关于fork，fork是在父进程的基础上，创建了一个新的进程，这个进程被称作子进程，子进程会得到父进程的数据、代码、堆和栈的副本，子进程和父进程有各自的地址空间，对空间更改不会影响到对方。&lt;br&gt;
这两者经常一起用，先用fork，然后用exec，也就是先创建了一个子进程，然后在子进程中用exec加载并运行新程序。&lt;/em&gt;/&lt;/p&gt;

&lt;p&gt;一般来说，只要确定了domain还有type，protocol直接就确定了，所以protocol一般设置为0，，但是也有一些例外，&lt;br&gt;
SOCK_DGRAM和 SOCK_RAW 的套接字发送的是数据包，用的是sendto和recvfrom。&lt;br&gt;
SOCK_STREAM套接字采用的是流式通信，用的是send和recv。&lt;/p&gt;

&lt;p&gt;可以对套接字用fcntl设置F_SETOWN，设置了这个以后，该套接字如果产生了SIGIO 或 SIGURG，可以由进程处理（当然要设置handler）（Set Owner）Using F_SETOWN is equivalent to an ioctl(2) call with the FIOSETOWN or SIOCSPGRP argument.&lt;br&gt;
setsockopt和getsockopt分别是用于设置和获取套接字选项。&lt;/p&gt;

&lt;p&gt;关于套接字的一些系统调用、库函数以及主题&lt;br&gt;
getaddrinfo(3), accept(2), bind(2),  close(2),  connect(2),  fcntl(2),  getpeername(2),  getsockname(2),  getsockopt(2),&lt;br&gt;
       ioctl(2), listen(2), read(2), recv(2), select(2), send(2), shutdown(2), socketpair(2), write(2), getpro‐&lt;br&gt;
       toent(3), address_families(7), ip(7), socket(7), tcp(7), udp(7), unix(7)&lt;/p&gt;
&lt;h3&gt;
  
  
  getaddrinfo(3)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;getaddrinfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;addrinfo&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;hints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;addrinfo&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;freeaddrinfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;addrinfo&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;gai_strerror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;errcode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;其中node是网址/域名，service是服务，比如http或https，然后hints用于指定期望返回得套接字地址类型的条件，简单说hints过滤了getaddrinfo返回的东西，然后res是一个指针，指向一个链表，链表中寸的都是符合条件的返回addrinfo结构体&lt;/p&gt;

&lt;p&gt;下面我们来看下addrinfo里面的内容：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;addrinfo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="kt"&gt;int&lt;/span&gt;              &lt;span class="n"&gt;ai_flags&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
               &lt;span class="kt"&gt;int&lt;/span&gt;              &lt;span class="n"&gt;ai_family&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
               &lt;span class="kt"&gt;int&lt;/span&gt;              &lt;span class="n"&gt;ai_socktype&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
               &lt;span class="kt"&gt;int&lt;/span&gt;              &lt;span class="n"&gt;ai_protocol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
               &lt;span class="n"&gt;socklen_t&lt;/span&gt;        &lt;span class="n"&gt;ai_addrlen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
               &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;sockaddr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ai_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
               &lt;span class="kt"&gt;char&lt;/span&gt;            &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ai_canonname&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
               &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;addrinfo&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ai_next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
           &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;//我们一般不用sockaddr，用的是sockaddr_in &lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;sockaddr_in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sa_family_t&lt;/span&gt;    &lt;span class="n"&gt;sin_family&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 地址族：AF_INET */&lt;/span&gt;
    &lt;span class="n"&gt;in_port_t&lt;/span&gt;      &lt;span class="n"&gt;sin_port&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="cm"&gt;/* 端口号 */&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;in_addr&lt;/span&gt; &lt;span class="n"&gt;sin_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="cm"&gt;/* IPv4 地址 */&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;sockaddr_in6&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sa_family_t&lt;/span&gt;     &lt;span class="n"&gt;sin6_family&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="cm"&gt;/* 地址族：AF_INET6 */&lt;/span&gt;
    &lt;span class="n"&gt;in_port_t&lt;/span&gt;       &lt;span class="n"&gt;sin6_port&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="cm"&gt;/* 端口号 */&lt;/span&gt;
    &lt;span class="kt"&gt;uint32_t&lt;/span&gt;        &lt;span class="n"&gt;sin6_flowinfo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* IPv6 流信息 */&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;in6_addr&lt;/span&gt; &lt;span class="n"&gt;sin6_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="cm"&gt;/* IPv6 地址 */&lt;/span&gt;
    &lt;span class="kt"&gt;uint32_t&lt;/span&gt;        &lt;span class="n"&gt;sin6_scope_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 范围ID（用于链路本地地址） */&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;1.ai_flags：标志位AI_PASSIVE将会返回一个通配地址，这个地址可以用于创建套接字并监听。AI_CANONNAME表示解析地址时返回关联的规范名称。AI_NUMERICHOST表示node参数已经是一个数字格式的IP地址了，不需要再DNS解析了。AI_NUMERICSERV表示service参数是一个端口号，而不是服务名。&lt;br&gt;
2.ai_family:AF_INET 表示IPv4，AF_INET6 表示IPv6。AF_UNSPEC获取任意类型的地址。&lt;br&gt;
3.ai_socktype：套接字类型，比如SOCK_STREAM代表流套接字，&lt;br&gt;
SOCK_DGRAM 代表数据报套接字。&lt;br&gt;
4.ai_protocol：协议类型，&lt;br&gt;
5.ai_addrlen是返回的套接字地址的长度，因为不同类型的地址具有不同的大小，比如IPv4和IPv6.&lt;br&gt;
6.ai_canonname：规范名，比如我们穿的node名字可能是google.com,但是规范名可能是www.google.com&lt;/p&gt;

&lt;p&gt;其中，当hints参数为NULL的时候，getaddrinfo就好像是设置了一个带有默认值的hints结构。具体详查。&lt;br&gt;
还有inet_aton可以把点分十进制ip地址转换成二进制的。&lt;/p&gt;

&lt;p&gt;addr.sin_addr.s_addr = INADDR_ANY; 像这种，就是说任何网络接口的连接请求都会被接收到，包括主机的公网地址，私网地址，本地回环地址等等。&lt;/p&gt;

&lt;p&gt;如何进行回环测试？以及node参数为NULL的时候？&lt;br&gt;
AI_PASSIVE 没有被设置&amp;amp;&amp;amp;当node参数不为NULL的时候，我们通过getaddrinfo可以返回一个可以主动发起连接的地址。&lt;br&gt;
AI_PASSIVE 没有被设置&amp;amp;&amp;amp;当node参数为NULL的时候，我们通过getaddrinfo返回的是回环地址，我们用这种回环地址可以确保客户端能够正常连接到服务器，即使没有实际的网络连接。&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
