
工程化C
文章平均质量分 78
从工程的角度,学习C语言
青衫客36
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
C语言中的野指针以及避免野指针的常用方式
在C语言中,(Dangling Pointer)是指一个指向无效或已释放内存区域的指针。使用野指针会导致不确定的行为,例如程序崩溃、数据损坏,甚至可能带来安全漏洞。freedelete。原创 2024-10-29 22:38:51 · 490 阅读 · 0 评论 -
再探mmap(Memory Mapped File)
mmap通过将文件内容映射到进程的虚拟内存空间,提供了一种高效、便捷的文件访问方式。它利用了虚拟内存管理的分页机制,使得文件访问像操作内存一样高效,特别适合处理大文件、进程间通信等场景。然而,由于它依赖操作系统的虚拟内存管理,因此也可能带来一些内存管理和同步问题。原创 2024-09-20 21:37:48 · 912 阅读 · 0 评论 -
C- 逻辑非 ! 和 位非 ~
关注的是逻辑真值(真/假),通常用于条件表达式。关注的是位级操作,用于执行位反转。在使用这些运算符时,需要确保理解它们的不同作用以及适用的上下文,因为混淆这两者可能导致完全不同的行为和结果。原创 2023-12-04 17:19:46 · 3279 阅读 · 0 评论 -
Linux多线程编程- pthread_self()
类型的,通常是一个无符号的长整型值,不过具体的类型是由实现定义的,这意味着它可以在不同的操作系统上有不同的表示。函数是 POSIX 线程库的一部分,它提供了一个非常简单的功能:获取当前线程的唯一标识符。在实现线程的同步操作时也很有用,例如,在一个线程中设置一个锁,并且只允许拥有这个锁的线程来释放它。该函数不接受任何参数,并且总是成功的,因此它没有返回错误代码。在上面的程序中,每个线程打印出它的线程ID。变量可以用来识别线程,但是在线程的执行函数内部,当我们调用这个函数时,它将返回当前线程的。原创 2023-11-04 18:34:45 · 582 阅读 · 0 评论 -
Linux多线程编程- pthread_detach()
函数是 POSIX 线程(pthreads)库的一部分,它用于将指定的线程置于分离状态(detached state)。分离状态的线程在终止时会自动释放其资源回操作系统,包括线程的堆栈和线程描述符。这意味着其他线程不需要并且也不能对分离线程调用来回收其资源。当创建一个线程时,默认情况下它是可结合的(joinable),这意味着其他线程可以通过调用等待该线程结束,并回收该线程结束时返回的资源。然而,在某些情况下,我们可能不需要等待线程结束,也不打算从线程收回任何值。在这种情况下,可以使用。原创 2023-11-04 18:18:28 · 2492 阅读 · 0 评论 -
C- struct stat 获取文件状态信息的结构体
是 C 语言中用于获取文件状态信息的结构体。它在 头文件中定义,主要通过 , , 和 等函数来填充其字段。以下是 的详细信息:定义:这个结构体包含了文件的基本信息,例如大小、所有者、权限、最后访问和修改时间等。函数:使用:通过调用 , , 或 函数并传递 结构体的地址作为参数,可以获取文件的状态信息。这些函数会填充 结构体的字段,以便我们可以检索所需的文件信息。例如,可以使用 结构体的 字段来获取文件的大小,或使用 字段来获取文件的权限和类型。 是一个非常重要和常用的结构体,它允许我们原创 2023-10-30 00:14:09 · 1823 阅读 · 0 评论 -
C- qsort()
qsort()是 C 语言标准库中的一个函数,用于进行数组的排序。其名字“qsort”代表“快速排序”(Quick Sort),这是因为它通常使用快速排序算法进行排序,但具体实现可能因库而异。以下是qsort()原创 2023-10-26 12:21:30 · 244 阅读 · 0 评论 -
C- fread() & fwrite()
fread()是 C 语言中的标准库函数,用于从文件或流中读取数据。它是一个非常强大且通用的函数,经常用于读取二进制文件,但也可以用于读取文本文件。原创 2023-10-24 23:17:22 · 1559 阅读 · 1 评论 -
C- strtok() & strtok_r()
strtok是 C 语言库中的一个函数,用于在字符串上执行分词操作。这意味着它可以用于将字符串分解成多个标记或段,这些标记之间由指定的分隔符分隔。以下是strtok。原创 2023-10-24 21:18:28 · 1307 阅读 · 1 评论 -
Linux网络编程杂谈(聊聊网络编程背后的故事)
以TCP为例,当 TCP 决定发送数据时,这些数据需要经过多个处理阶段才能真正被传输到物理网络。其中一个关键步骤是将数据移动到网络接口卡 (NIC)。这个过程的各种优化和细节可能会依据操作系统、NIC 设计和网络配置而有所不同,但上述流程为数据在大多数现代系统中的通常路径提供了一个概述。原创 2023-10-22 12:31:36 · 433 阅读 · 0 评论 -
HTTP协议中的\r\n
当处理跨平台的文本文件或数据传输时,很容易遇到与行结束符相关的问题,尤其是当文件从一个系统转移到另一个系统时。: Carriage Return + Line Feed (回车+换行),对应连续的ASCII码为13和10的字符,通常表示为。在现代计算机系统和网络协议中,这种区分不再必要,但由于历史原因,很多文本和协议(包括HTTP)仍然使用。: Line Feed (换行),对应ASCII码为10的字符,通常表示为。这种表示法是从早期的电信和计算机通信中继承过来的,其中。是用来表示行的结束的。原创 2023-10-21 19:22:11 · 2158 阅读 · 0 评论 -
Linux网络编程-极简HTTP&UDP服务器
80802048然后在浏览器或者使用curl工具访问http://localhost:8080,应该能够看到“Hello, World!”的响应。原创 2023-10-21 18:36:48 · 597 阅读 · 0 评论 -
C- 使用原子变量实现信号量
信号量(Semaphore)是并发编程中的一个核心同步原语,它在多进程和多线程环境下被设计用来协调不同的执行单元,确保它们在对共享资源的访问上达到同步和互斥。信号量内部维护一个计数器,该计数器的初始值可以被视为可用资源的数量。当一个进程或线程试图“获取”一个信号量时,该计数器会递减;当它“释放”信号量时,计数器则递增。如果计数器的值达到零,任何试图获取信号量的操作都会被阻塞,直至其他进程或线程释放资源。原创 2023-10-19 23:43:38 · 599 阅读 · 0 评论 -
C语言- 原子操作
原子操作为C程序员提供了一种在高度并发的环境中对数据进行高效、安全操作的方法,无需使用复杂的同步原语。然而,正确和高效地使用原子操作需要对内存模型、内存顺序和硬件的实际行为有深入的了解。原创 2023-10-19 22:20:17 · 5733 阅读 · 0 评论 -
C- 使用原子变量实现自旋锁
自旋锁(Spinlock)是一种常用于多线程编程中的低开销锁,其特点是当线程尝试获取锁而锁已被其他线程占用时,该线程会处于一个持续的忙等待(busy-wait)状态,直到它可以获取到锁为止。这种方法避免了线程切换和上下文切换的开销,但是如果锁被持有的时间较长,它可能会造成CPU时间的浪费。:当需要保护的代码执行非常快,锁的持有时间非常短时,自旋锁是非常有效的。:当很少有线程试图同一时间获取锁时,自旋锁是有用的。原创 2023-10-19 21:38:58 · 1520 阅读 · 0 评论 -
warning: implicit declaration of function ‘sleep’ [-Wimplicit-function-declaration]引出的思考
这个警告出现是因为在代码中使用了sleep函数,但是没有包含相应的头文件,导致编译器发出“隐式声明的函数”警告。sleep函数是定义在unistd.h头文件中的。加入这一行后,再次编译代码,警告就会消失。原创 2023-10-17 15:14:52 · 1740 阅读 · 1 评论 -
Linux多线程编程- 条件变量(Conditional variable)
在多线程环境中,条件变量提供了一种方式,使得一个线程可以等待某个特定条件成为真,而另一个线程在该条件成为真时可以通知等待线程。原创 2023-10-17 14:56:55 · 1071 阅读 · 0 评论 -
Linux- 命名信号量和无名信号量的区别
总的来说,区分这两种信号量类型的主要原因是因为进程和线程之间有基本的差异。进程通常是独立的、隔离的执行实体,拥有自己的地址空间。线程,另一方面,是进程内的轻量级实体,共享相同的地址空间。因此,进程间同步需要一个跨进程的可见机制,而线程间同步则可以在单一地址空间内完成。:无名信号量存在于进程的地址空间中,它们不关联任何外部的名称。命名信号量和无名信号量之间的区别主要在于它们的可见性、生命周期以及如何在进程或线程之间共享。在一个进程内,所有线程共享相同的内存空间,所以它们可以直接访问和操作同一个无名信号量。原创 2023-10-16 23:12:33 · 522 阅读 · 0 评论 -
Linux多线程编程- 无名信号量
无名信号量(在 POSIX 环境下通常指sem_t类型的信号量)是用于同步和互斥的原语,它允许线程和进程按照预期的顺序执行,并确保对共享资源的安全访问。无名信号量与命名信号量的主要区别在于它们的可见性和生命周期。无名信号量通常用于一个进程内的线程间同步,而命名信号量用于多个进程间的同步。原创 2023-10-16 23:10:43 · 427 阅读 · 0 评论 -
Linux多线程编程- 命名信号量
命名信号量是一种同步原语,主要用于进程间同步和通信。它们在不同的进程之间是可见的,因此可以用来控制多个进程对共享资源的访问。原创 2023-10-16 22:44:13 · 447 阅读 · 0 评论 -
C多线程编程- 近似求解π
基于这些线程的结果,程序计算在单位圆内的点的比例,并乘以4来估算π的值。为了对比,程序还直接在主线程中(没有并发)进行了相同的π估算过程(由于每次都是生成随机数,所以这个基准也没啥意义hh~)。最后,程序打印出两种方法得到的π值。在上面的程序中,为每个线程都动态分配了 arg_t 结构的内存,但在线程执行完毕后,这些内存并没有被释放。仔细观察上面的程序,我使用了一个固定大小的线程数组:pthread_t tids[N1];这样,每次线程执行完毕并被主线程收回后,对应的动态分配的内存都会被释放。原创 2023-10-15 16:00:50 · 640 阅读 · 0 评论 -
Linux- 自定义一个ARP请求
自定义一个ARP请求或响应,并使用AF_PACKET套接字发送,需要手动创建整个以太网帧。:运行此代码需要root权限,因为使用AF_PACKET需要对网络接口有完全的访问权限。而且,确保修改代码中的TARGET_IP和INTERFACE_NAME为我们想要查询的目标IP和我们使用的网络接口名。这只是一个简单示例,可以根据需要进行修改和扩展。如何设置mac地址为 00:15:5d:31:81:8c?为了设置MAC地址为,不能使用memset,因为memset会将同一个值设置到所有的字节中。原创 2023-10-14 22:33:17 · 625 阅读 · 0 评论 -
Linux网络编程- struct packet_mreq & setsockopt()
是一个数据结构,用于 Linux 中的原始数据包套接字,当我们想改变套接字的行为以接收特定类型的数据包时,它与函数配合使用。下面是mr_addressmr_type而如果想加入一个特定的多播地址,则设置mr_type为,并提供相应的多播MAC地址。原创 2023-10-10 23:59:15 · 939 阅读 · 0 评论 -
Linux网络编程- 开启混杂模式(PROMISC)的两种方式
在开发抓包工具或网络监控应用程序时,通常选择哪种方法取决于具体需求。如果只是想要为特定的捕获会话设置混杂模式,而不影响系统上的其他应用程序,使用。如果需要在设备级别更改接口的状态,并希望所有应用程序都能在混杂模式下看到数据包,那么使用。两者都使网络接口能够捕获所有经过的数据包,而不仅仅是发往接口的数据包。以下两种方式都是用于开启混杂模式,但它们的工作方式略有不同。原创 2023-10-11 00:13:43 · 2908 阅读 · 0 评论 -
Linux网络编程- recvfrom() & sendto()
recvfrom()函数是一个系统调用,用于从套接字接收数据。该函数通常与无连接的数据报服务(如 UDP)一起使用,但也可以与其他类型的套接字使用。与简单的recv()函数不同,recvfrom()可以返回数据来源的地址信息。:一个已打开的套接字的描述符。:一个指针,指向用于存放接收到的数据的缓冲区。:缓冲区的大小(以字节为单位)。:控制接收行为的标志。MSG_PEEK:一个指针,指向一个sockaddr结构,用于保存发送数据的源地址。:一个值-结果参数。开始时,它应该设置为src_addr缓冲区的大小。原创 2023-10-07 23:16:05 · 12017 阅读 · 0 评论 -
Linux网络编程- 原始套接字(Raw Socket)
原始套接字(Raw Socket)提供了一种机制,允许应用程序直接访问底层传输协议,绕过操作系统提供的传输层接口。这种套接字通常用于实现新的协议或对现有协议进行低级别的操作。以下是对原始套接字的详细介绍:定义与用途:创建:特权:工作方式:用途与限制:注意事项:跨平台的差异:总的来说,原始套接字是一个非常强大的工具,但也需要谨慎使用。正确使用它需要对网络协议有深入的理解,而滥用它可能导致网络问题或被视为恶意活动。创建链路层的原始套接字允许我们直接与链路层设备(例如以太网适配器)交互,从而可以发送和接收链路层帧原创 2023-10-07 22:47:51 · 6437 阅读 · 0 评论 -
C- 静态链接
静态链接意味着在编译时将所有库函数直接嵌入到最终的可执行文件中,而不是在运行时通过共享库来动态链接这些函数。静态链接的结果是一个更大的可执行文件,因为它包含了所有必要的代码,但它可以在没有外部依赖的情况下独立运行。在 Unix-like 系统上,静态库实际上就是一个包含了多个对象文件的归档文件。这个例子展示了如何创建、编译并静态链接一个简单的库。对象文件,同时为库构建一个索引,以加速后续的链接过程。: 这是要创建或修改的静态库的名称。选项告诉编译器链接我们的静态库。: 这是要添加到静态库的对象文件。原创 2023-09-30 21:27:57 · 241 阅读 · 0 评论 -
C- 动态链接
这就是为什么应用程序和系统管理员必须确保共享库的完整性和来源,并使用如 AppArmor、SELinux 或其他MAC (Mandatory Access Control) 系统,以及数字签名来确保只加载和执行受信任的代码。在C语言中,动态链接指的是在程序运行时动态加载和链接库的过程,而不是在编译或链接时。如果某个应用期望使用一个特定的共享库,但由于某种原因(例如攻击者替换了共享库或错误的配置),它加载了一个不同的库,那么应用的行为可能会完全不同,甚至可能是恶意的。选项指定库的名字,并使用。原创 2023-09-30 20:32:24 · 326 阅读 · 0 评论 -
C- 一个程序引发的问题
因此,在实际编程中,应尽量避免使用这样的方式。但在同一语句中进行声明和初始化时,该语句的声明部分会首先被处理。,但需要知道系统的指针大小(通常是 4 字节(32位系统)或 8 字节(64位系统))。因为我们最终的目标是更改一个指针的值(指向一个新的字符串),而不仅仅是更改一个字符。的值,首先,需要确保准确地计算了偏移量,并且将正确的值赋给正确的地址。是右结合的,但在整个声明和初始化过程中,声明总是先于初始化发生。关于第一种写法的问题,这实际上与C语言的声明和初始化语法有关。是一个类型,而不是一个变量。原创 2023-09-29 18:38:16 · 177 阅读 · 0 评论 -
C- 可变参数的简单版实现
可变参数函数的声明要包含至少一个固定的参数,后跟省略号...。va_list是一个在stdarg.h中定义的类型,通常是一个指针类型,但它的具体实现是特定于体系结构和编译器的。通常,它可能是一个指向栈上当前位置的指针。va_list是一个为了访问和遍历可变参数而设计的数据类型。它通常是一个指向栈的指针,指向当前可变参数的位置。虽然它在高层次上相对简单,但在底层,其具体实现取决于特定的编译器和体系结构,因此通常隐藏在stdarg.h宏后面,为程序员提供一个清晰且跨平台的接口。原创 2023-09-29 11:55:45 · 292 阅读 · 0 评论 -
C- 内联汇编实现puts函数
这是一个用GCC扩展的语法书写的内联汇编代码块。它直接使用x86-64架构上的汇编指令来调用Linux的系统调用。: Clobbered register list,告诉编译器这些寄存器的值在汇编代码块中已被修改。但在这段代码中,我们没有看到这些宏的定义。函数使用内联汇编直接与Linux内核进行交互,将字符串。该函数最后返回写入的字节数,或在出错时返回一个负值。函数,它使用内联汇编在Linux上直接执行。: 将字符串的地址设置为第二个参数。最后,系统调用的返回值(在。,即系统调用的返回值)。原创 2023-09-27 23:24:43 · 423 阅读 · 0 评论 -
Linux网络编程- ioctl()结合struct ifreq使用案例
当我们使用ioctl()函数和请求码来获取网络接口的标志时,我们需要提供一个结构体作为参数。这个结构体包含了网络接口的名称和一个将被填充的字段,该字段将在调用返回时包含所请求的标志。原创 2023-09-27 14:47:03 · 353 阅读 · 0 评论 -
Linux网络编程- struct ifreq & ioctl() 系统调用
是一个数据结构,用于各种与接口相关的输入/输出控制 (ioctl) 调用。它的主要用途是在网络编程中获取和设置网络接口的属性。这个结构体在头文件中定义。以下是: 一个字符数组,表示接口的名称,如 “eth0”, “wlan0” 等。: 一个类型的结构,表示接口的地址。: 同样是一个类型的结构,表示接口的网络掩码。: 表示接口的广播地址。: 表示接口的标志,如IFF_UP(接口正在运行)、(接口支持广播)、(接口在混杂模式下)等。: 表示接口的硬件(通常是 MAC)地址。原创 2023-09-27 14:11:16 · 5904 阅读 · 0 评论 -
Linux网络编程- sockaddr & sockaddr_in & in_addr
是用于通用的套接字地址结构体,通常在多种网络API调用中被用作参数,尤其是在套接字编程中。它是许多具体套接字地址结构体(例如用于IPv4、用于IPv6)的超类或通用类型。原创 2023-09-27 13:39:26 · 1423 阅读 · 0 评论 -
Linux网络编程- ether_header & iphdr & tcphdr
是一个数据结构,用于表示以太网(Ethernet)帧的头部。这个结构体在头文件中定义。当你处理或分析以太网帧时,可以使用这个结构体来访问和解读 Ethernet 头部的各个字段。以下是: 目标 MAC 地址 (Destination MAC address),一个 6 字节的数组。: 源 MAC 地址 (Source MAC address),一个 6 字节的数组。: 帧类型或以太网协议。这个字段表示载荷的类型/协议。例如,如果值是 0x0800,那么载荷是一个 IPv4 数据包;原创 2023-09-27 11:52:18 · 2047 阅读 · 0 评论 -
Linux网络编程- inet_pton() & inet_ntop()
函数是 “Internet presentation to network” 的缩写,用于将 IP 地址的表现形式(例如字符串形式的 “127.0.0.1”)转换为其网络字节序的二进制形式。这个函数支持 IPv4 和 IPv6 地址。原创 2023-09-26 22:20:30 · 1695 阅读 · 0 评论 -
Linux- 网络编程初探
原始套接字(Raw Socket)是一种提供较低级别网络访问的套接字。通过使用原始套接字,应用程序可以直接发送或接收网络层如IP的数据包,或者传输层如TCP、UDP的段,而无需通过常规的套接字API提供的协议处理。:使用原始套接字,你可以操作或构建自己的协议,或者直接与现有协议(如ICMP)交互。:通常,当发送或接收数据包时,操作系统内核会为你处理很多细节,例如TCP的三次握手或IP头的填充。但是,使用原始套接字,你可以直接构建或解析这些协议,从而绕过标准的内核处理。原创 2023-09-26 21:10:56 · 448 阅读 · 0 评论 -
Linux网络编程- 网络字节顺序
网络字节顺序是一种规定的数据表示格式,被用于TCP/IP协议栈,特别是在网络传输数据时。它确保不同的计算机和架构之间可以无缝地通信。网络字节顺序是大端字节序(big-endian)。原创 2023-09-26 20:40:00 · 350 阅读 · 0 评论 -
C- strncmp() & strncpy()
strncmp是 C 语言中的一个标准库函数,用于比较两个字符串的前n个字符。此函数是头文件的一部分。原创 2023-09-25 10:46:44 · 219 阅读 · 0 评论 -
Linux- POSIX共享内存对象
POSIX共享内存对象是一种允许多个进程共享一个给定名称的内存区域的机制。这些共享内存对象通常与POSIX信号量结合使用,以实现进程之间的同步。共享内存是IPC(进程间通信)机制中最快的方法之一,因为它允许进程直接访问同一块内存,而无需进行任何数据复制。原创 2023-09-24 22:56:57 · 334 阅读 · 0 评论