IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

标签:C

共 71 篇相关文章

IT 累计浏览 2,419

libev ev_io源码分析

这篇深入分析了libev事件库中负责I/O事件监听的ev_io组件。作者从项目实践中的疑问出发,首先梳理了libev的核心抽象:所有watcher的基类`ev_watcher`,以及统一管理所有watcher状态的`ev_loop`结构。 文章重点剖析了ev_io的实现机制。它解释了ev_io如何“继承”`ev_watcher_list`以实现链表管理,并与一个名为`ANFD`的结构(用于映射文件描述符与事件链表)协同工作。对ev_io最关键的几个操作——添加、执行回调和删除——进行了流程拆解。 例如,添加watcher时并非立即调用`epoll_ctl`,而是先记录到一个待处理队列中,在下次循环的`epoll_wait`前才批量修改内核事件,这是一个精巧的优化。唤醒与回调过程则展示了如何根据epoll返回的结果,从事件链表中找到匹配的watcher并触发其回调函数。 整体来看,这篇文章清晰地展示了libev如何用简洁的C结构实现高效的事件驱动模型,对于想理解事件循环底层机制,特别是I/O多路复用与应用层封装之间交互的开发者来说,提供了很好的实现视角。

IT 累计浏览 2,232

C语言可变参数函数取参方法

这篇讲的是C语言中可变参数函数的具体取参方法。大家对 `printf` 这类函数很熟悉,它们允许传入不定数量的参数,但具体是如何在函数内部“逐个取出”这些参数的呢? 文章从 `...` 和 `` 头文件讲起,核心对比了 `va_list`、`va_start`、`va_arg`、`va_end` 这一套标准宏的使用流程。作者通过一个简单的“求和函数”示例,展示了如何声明可变参数、初始化参数列表指针,然后用循环和 `va_arg` 按类型逐个提取参数值。 除了标准方法,文章也提到了在非主流平台或特定编译器下可能存在的其它取参机制。关键差异在于:标准宏方法通过一个连续的参数栈来工作,类型信息在取参时需要手动指定,这既是它的灵活性,也是潜在的风险点——如果声明的类型与实际传入不符,就会导致未定义行为。 因此,文章也隐含了一个结论:可变参数函数非常灵活,但像 `printf` 那样需要根据第一个格式字符串来“理解”后续参数,这要求开发者对底层取参机制有清晰的认识,才能安全、正确地使用它。

IT 累计浏览 3,235

c关键字-sizeof的种种

这篇技术博客深入探讨了C语言中一个常被误解的关键字——`sizeof`。作者从它作为编译时关键字而非函数或宏的核心身份切入,剖析了其值在编译阶段确定的根本特性。 文章通过一系列经典且易错的示例,直观展示了`sizeof`在不同上下文中的行为差异。例如,它对数组名和指针的计算结果完全不同,这一细节是许多C程序员必须厘清的知识点。同时,文章也详细讲解了`sizeof`对结构体、联合体等复合类型大小的计算规则,包括对齐方式可能带来的影响。 作者的讲解侧重于原理与实践的结合,帮助读者理解编译器是如何思考并计算这些大小的。掌握这些细微之处,能让你在编写涉及内存分配、数据结构布局的代码时,做出更精准的判断,从而避免潜在的内存错误。

IT 累计浏览 2,986

Skynet 设计综述

这篇讲的是知名游戏服务器框架Skynet的C版本从零构建过程。作者在一个月内完成了框架开发,期间对多个模块进行了反复重构,最终将代码精简至仅六千余行C代码与一千余行Lua代码。文章透露出作者对代码质量与可维护性的坚持:在紧凑的篇幅内保持清晰结构,以期后续Bug能够被快速定位与修正。这种对“小而精”设计目标的追求,展现了作者对底层框架工程化的深刻理解——用精炼的代码承载高并发的服务框架,本身就是一项充满挑战的设计实践。

IT 累计浏览 1,964

lua metatable使用和源码分析(三)

这篇是“Lua元表源码分析”系列的第三篇,将视角从用户自定义表转向了Lua的基础——数字、字符串等基本类型是如何挂载并使用元表的。作者并没有停留在“数字也有元表”这个结论上,而是带着读者钻进源码,看Lua的实现者如何为这些内建类型维护和查找它们的元表。 文章的核心在于剖析`luaL_getmetafield`等关键函数的实现逻辑。最巧妙的一点在于,Lua并非为每个数字都存储一个元表,而是在`lua_State`或全局状态中,为数字、字符串等不同类型分别维护了一个共享的、静态的默认元表。源码分析揭示了当对数字调用方法时,虚拟机是如何一步步索引到这个全局默认元表,并执行其中定义的`__add`、`__index`等元方法的。这个设计既保证了功能的完整性,又极大地节省了内存。 通过这篇分析,读者不仅能理解“如何用”,更能看清Lua为了保持语言的一致性和性能,在底层做出的精巧权衡。它清晰地展示了,用户定义的元表机制与语言内建的元表机制,是如何在同一套引擎规则下协同工作的。

IT 累计浏览 4,477

“好奇号”火星车和它搭载的软件(来自Erlang程序员的观点)

这篇讲的是,地球到火星长达20分钟的通信延迟下,NASA的“好奇号”火星车如何依靠软件实现高度自主的故障应对。文章从一位Erlang程序员的视角出发,带我们审视这套“地外”软件系统的精妙设计。 作者重点剖析了火星车软件的核心挑战:在无法即时干预、硬件资源有限且环境极端恶劣的条件下,确保系统的长期可靠运行。他将目光投向了Erlang这门以并发、容错和分布式著称的语言,并非因为它被直接使用,而是其蕴含的“let it crash”哲学和热代码升级等思想,与火星车软件的设计理念不谋而合。例如,当遇到未预期的传感器故障时,系统需要能像Erlang的监督树那样,快速隔离问题、重启关键进程,而不是导致整体停摆。 文章没有停留在理论对比,而是具体到了“好奇号”如何管理自身的有限计算资源,以及如何将复杂的任务序列转化为能在不同威胁级别下执行的自主指令集。这种将高可靠性理论(如Erlang)与极端工程实践相结合的分析,为嵌入式系统、分布式开发乃至高可靠架构设计提供了宝贵的跨界启发。

IT 累计浏览 2,115

Skynet 的一些改进和进展

作者近期将重心完全放到了Skynet框架的开发与演进上。作为一款轻量级、高并发的游戏服务器框架,Skynet的持续改进一直是社区关注的焦点。 这篇内容并非泛泛而谈,而是聚焦于框架在实际迭代中发生的数项具体改进。作者从近期的工作出发,分享了在多个方向上的进展,其中既可能包含对核心调度模型的优化,也可能涉及关键模块的功能增强与性能提升。文章以第一手的开发视角,阐述了为何要做这些改动、设计思路如何,以及改进后的初步效果,为理解框架的演进脉络提供了直接线索。 对于关注游戏服务器与高并发系统架构的读者而言,这篇分享提供了宝贵的工程实践参考,展示了如何在一个成熟的开源框架上进行持续优化。

IT 累计浏览 7,929

websocket 连接 C Server的尝试

这篇讲的是作者在C语言服务器上实现WebSocket连接的完整实践。作者从项目需要实时通信的需求出发,决定尝试在轻量级的C服务器上直接集成WebSocket支持,而非依赖现成的Node.js或Go生态。 文章详细拆解了其中的核心挑战:如何用C底层处理WebSocket的帧封装、握手升级以及持久连接的管理。作者重点分享了对WebSocket协议握手过程的解析与响应构建,以及如何利用epoll实现高效的非阻塞I/O处理,确保在单线程模型下也能支撑大量并发长连接。 实践中遇到的一个典型问题是粘包处理,作者通过设置明确的帧边界解析状态机来解决。最终,这个基于C的实现达到了预期的低延迟和高吞吐量性能,资源占用也远低于解释型语言方案。对于想深入理解网络协议细节、或在资源受限环境中构建高性能服务的开发者,这篇文章提供了一个清晰的实战参考。

IT 累计浏览 10,037

PHP程序的执行流程

这篇讲的是,要开发PHP扩展,必须先摸清PHP程序从代码到运行背后的完整执行路径。作者从这个明确的开发动机出发,拆解了PHP引擎处理请求的整个生命周期。 核心思路是,将执行流程作为“地图”,指引扩展开发者在正确的位置“插入”自己的代码。文章会聚焦于Zend引擎如何解析、编译、执行OPcode,以及扩展可以在哪些关键阶段(如模块初始化、请求初始化、函数调用等)进行挂钩和干预。 理解这个流程的巧妙之处在于,它能让你不再“盲目”地写扩展,而是能精准地知道在哪个环节扩展代码会被执行、能获取到什么信息、以及如何与引擎核心交互。这对于想从用户空间深入引擎内部的开发者来说,是搭建知识地基的关键一步。

IT 累计浏览 1,978

C函数串接的几种手法

作者针对“如何将多个业务处理函数串行调用”这个C语言开发中的常见需求,介绍了几种实现函数串接的具体手法。文章并非泛泛而谈,而是直接切入实践,展示了通过函数指针数组、宏封装以及利用回调机制等不同思路来组织代码的方法。 对比的核心在于代码的灵活性与耦合度:使用函数指针数组可以在运行时动态决定调用序列,适用于流程可变的场景;而利用宏进行声明式封装,则能在编译期生成更紧凑、执行效率更高的串接代码,适合对性能要求较高的固定流程。文章还探讨了如何利用上下文结构体为这些串接的函数传递状态,这是实现复杂链式调用的关键。 作者通过对比不同方案的代码组织复杂度与运行开销,给出的选择思路是:对于快速原型或流程频繁变更的场景,灵活的函数指针方案更便捷;对于核心且稳定的处理管线,编译时确定的宏或内联方式通常性能更优。这种基于实际约束的权衡,能帮助读者在具体项目中做出更合理的设计选择。

IT 累计浏览 8,735

nginx自定义模块编写-实时统计模块

这篇讲的是作者在已有编写Nginx模块的经验基础上,挑战实现一个更贴近底层的“实时统计”过滤模块。他并非从零开始,而是先点明了自己之前处理过基于POST参数路由的“处理模块”,从而自然引出本次编写“过滤模块”的不同挑战与思考。 文章的核心在于具体实现。作者没有停留在概念上,而是直接切入过滤模块如何在Nginx请求处理流程中(在内容发送给客户端前)插入统计逻辑。他分享了如何从模块的注册、初始化,到编写核心的过滤函数来遍历并记录响应数据的关键步骤。这种“边做边讲”的方式,让读者能清晰看到从需求(实时统计)到代码落地的完整路径,其中对Nginx内部数据结构和回调机制的运用是文章的精华所在。 对于想深入理解Nginx扩展机制或需要进行流量分析、监控的开发者来说,这篇实践记录提供了清晰的思路和可复用的代码框架。它展示了如何将一个具体的业务需求,转化为一个高效的Nginx内置功能。

IT 累计浏览 3,036

浅析Linux Kernel 哈希路由表实现(二)

这篇讲的是Linux内核在发送数据包时,如何通过一个清晰的函数调用链找到路由的实现细节。作者从外层函数ip_route_output_key()出发,一步步追踪到最终的执行者__ip_route_output_key()。 核心焦点就集中在__ip_route_output_key()这个函数上。它是内核路由查找的真正引擎,负责根据目标地址、源地址等关键信息,在哈希路由表中高效地匹配出最佳路由项。文章没有停留在概念层面,而是直接潜入内核源码,剖析这个函数如何处理不同的查找场景,比如它是如何利用路由缓存加速,以及在复杂情况下如何进行精确的匹配与回溯。 通过这样的分析,读者能清晰地看到内核网络栈为了兼顾性能与准确性,在路由查找路径上做出的精巧设计。这种对底层实现逻辑的拆解,对于理解数据包的旅程和网络性能优化都很有启发。

IT 累计浏览 3,707

浅析Linux Kernel中的那些链表

这篇讲的是Linux内核中链表的实现。作者从内核开发者最熟悉的链表结构切入,指出它与数据结构教材中的标准链表有着本质区别。 文章的核心在于剖析内核链表的巧妙设计。它并非传统意义上“节点包含数据”,而是采用侵入式设计:链表节点(`list_head`)被嵌入到你想要管理的数据结构本身中。这样,一套通用的链表操作代码就能管理任意类型的数据,无需为每种数据重写实现。 作者详细对比了侵入式链表与非侵入式链表的差异。传统链表需要为数据分配单独的节点内存,而内核链表将节点与数据合为一体,在内存管理上更为高效和灵活。这种设计使得通过一个数据结构中的链表节点,可以反向定位到包含它的整个结构体,这是理解后续很多内核数据结构(如进程队列)的关键。 文章最后可能总结,这种设计牺牲了一点点直观性,但换来了极大的通用性、性能和内存效率,是内核编程中“空间与时间”、“通用与专用”权衡的经典范例。对于想深入理解内核源码的开发者来说,厘清这个基础结构至关重要。

IT 累计浏览 2,583

Apache基础数据结构(tables)代码浅析

这篇讲的是Apache HTTP Server(httpd)中一个基础且关键的数据结构——`tables`。在众多轻量级Web服务器涌现的今天,这篇分析直接深入到这位“老兵”最核心的C语言源码之中。 作者从`tables`如何存储和管理键值对(如HTTP头、环境变量)入手,剖析了其内部实现。文章不仅展示了它用数组和哈希表结合的灵活内存布局,还特别点出了其内存预分配、按需增长的“惰性”策略,以及在查找、插入、迭代操作上如何权衡性能与内存占用。 这些看似朴素的设计,在并发处理海量请求时,恰恰是高效且稳定的基石。对于想理解高性能C项目如何设计基础组件、或对Apache内部机制感兴趣的读者,这篇文章提供了一个很好的微观窗口,其思路对优化其他C语言项目的数据容器也有借鉴意义。

IT 累计浏览 3,706

Protocol Buffers for C

这篇讲的是作者对 Protocol Buffers 在 C 语言环境下的实现现状感到不满,并由此展开的一番技术思考。作者从实际使用体验出发,指出了一个普遍存在的痛点:Google 官方 Protocol Buffers 主要为 C++ 生成大量代码,这让追求轻量和高效的 C 开发者感到负担。同时,官方并未提供原生的 C 版本支持,而社区维护的第三方 C 实现又因设计或功能问题,未能完全满足他的需求。 这种不满并非单纯的抱怨,而是触及了跨语言工具设计中的一个核心矛盾:如何在保证序列化效率和功能完整性的同时,适配不同语言生态的哲学与实践习惯。对于 C 语言,开发者往往更青睐显式、可控且资源占用低的方案。作者的审视实际上代表了一部分技术用户对“工具是否真正贴合语言特性与开发者心流”的深度关切。 因此,这篇文章与其说是在推荐一个现成的解决方案,不如说是在呈现一个精于技术的从业者,面对不趁手工具时的典型思考路径:从识别问题根源(代码生成模式与语言范式不匹配),到评估现有替代品的不足,最终勾勒出对一个更理想、更纯粹的 C 实现的潜在期待。这对于那些同样在寻找高效数据交换方案,或正在设计跨语言工具的读者,提供了一个非常具体的观察视角。

IT 累计浏览 2,859

最奇特的编程语言特征

这篇文章从一个技术社区的热门讨论切入,探讨了各类编程语言中最“奇特”甚至“反直觉”的语法特性。作者以LISP那标志性的、层层嵌套的括号为例,指出这类特征因其不符合常规思维习惯而常被诟病,但它并非个例。 文章核心来自一个征集帖,其中收集了超过320个来自不同语言的“奇特”代码片段。据观察,JavaScript在这方面“问题”最多,C、Java、Python、PHP等主流语言也榜上有名。这些特性可能让初学者摸不着头脑,有的却暗含语言设计的深层逻辑。 作者并未止步于猎奇,而是通过汇总这些案例,揭示了语言设计中“合理”与“反常”之间的有趣张力。读完能让你意识到,那些看似“奇怪”的语法,或许正是理解一门语言哲学和历史背景的一把钥匙。

IT 累计浏览 2,220

保持简单----纪念丹尼斯o里奇(Dennis Ritchie)

这篇文章是作者受财新网之邀,为纪念刚离世的计算机大师丹尼斯·里奇所写。文章没有罗列其作为C语言和Unix创造者的丰功伟绩,而是抓住了里奇一生所践行的核心编程哲学——“保持简单”。 作者从里奇那些看似简洁甚至“简陋”的设计入手,阐述了这种简单并非简陋,而是一种深刻的洞察力与工程上的克制。文中探讨了里奇如何用最少的元素构建出强大而灵活的系统,以及这种哲学如何深刻影响了整个现代软件世界的根基。它提醒我们,在追求功能与炫技的时代,真正的智慧往往体现在对复杂性的有效驯服与舍弃上。 这篇文章更像是一次对技术初心的回望,让读者在缅怀大师的同时,重新思考自己编码与设计时的根本立场。

IT 累计浏览 4,852

那些曾伴我走过编程之路的软件

这篇讲的是作者从一张尘封的 VC++6.0 光盘出发,开启的一场个人编程软件怀旧之旅。文章并未停留在简单的软件罗列,而是借此追溯了从 Turbo C 2.0 到 Visual C++ 6.0 等经典工具如何陪伴他度过编程学习的早期岁月,以及这些工具背后所代表的技术演进脉络。 作者以轻松而略带感慨的口吻,反思了当年使用这些软件时的想法与如今视角下的差异,生动体现了技术变迁带来的冲击与趣味。尽管 Unix/Linux 作为其后期专长未在此展开,但早期 Windows 平台开发工具的点滴回忆已足以引发许多同行者的共鸣。 这篇文章像一位老朋友的叙旧,通过具体的软件细节与个人体验,让读者也能回溯自己的编程起点,感受技术世界日新月异中那些不变的初心与乐趣。

IT 累计浏览 5,474

php多线程扩展

这篇讲的是作者用C语言动手写了一个PHP多线程扩展的实践。作者从社区中关于PHP能否以及是否需要多线程的争论出发,指出既然PHP内核是C,理论上C能实现的功能PHP也能触及。因此,他编写了一个相对简单的扩展,核心思路是创建与退出线程。 为了兼顾服务器性能,扩展设置了线程数上限,即当前CPU核心数的两倍。文中给出了创建线程的基础代码示例,主要面向的是有类似需求、想进行底层探索的开发者。这种直接动手验证想法的路径,为理解PHP与操作系统线程的交互提供了非常直观的参考。

IT 累计浏览 3,604

printf-小代码,大问题

这篇讲的是C/C++中最基础的printf函数可能带来的隐患。作者从大家最熟悉的代码入手,带领读者重新审视这个“小”工具在实际开发中可能引发的“大”麻烦。文章没有空谈理论,而是直接通过在SUSE 10 32位系统上编译测试的具体代码案例,揭示了那些容易被忽略的细微陷阱。 这些陷阱的根源,往往在于开发者对语言特性或系统行为的想当然理解。文章通过深入分析这些看似不起眼的代码在特定环境下的真实表现,展示了它们如何导致非预期的结果甚至潜在的严重问题。对于日常使用printf的C/C++开发者来说,这篇文章提供了一个宝贵的视角,提醒大家即便是最常用的工具也需要保持敬畏和审慎。