睡不着写点,

一位软件工程毕业生分享了他对大学生涯的反思,包括专业知识的欠缺和对未来职业生涯的规划。在经历了多家公司的工作后,他选择了互联网行业,并计划在安全领域深耕。文章还探讨了在甲方或乙方工作的优劣,以及个人兴趣与职业发展之间的平衡。

这么晚睡不着,所以写点博客,其实就是对自己的一点小总结吧:)

1 学业

明天要回学校取毕业证和学位证,马上就要本科毕业了,有时候会觉得知识永远是学不完的。其实作为一名软件工程的学生来说,我只是在写出了一些丑陋的代码,又经过自己的否定又否定之后,根据“软件工程”的做法去重新设计模块,甚至养成了严格需求分析的习惯。但从计算机的角度来说,我是失败的。我没有在大学几年中认真地打好“操作系统”,“算法”等专业课的基础。其实很多时候都可以感受到自己基础知识的匮乏,包括现在也是,所以总想找个契机好好补一下。希望能够一点一点来吧。

在学业上,有想过通过考研来提升一下自己,全日制的竞争太大,非全的因为各种原因最后也没复习成,GG。

2 工作

目前为止已经是第三家公司了,也是马上要签正式合同的公司。

第一家时候很懵懂,很多东西都不懂,只是因为自己年纪小,办事处又缺人,可能就通过面试了,但这家公司对我的积极影响很大。

第二家是一个互联网公司,大三暑期找的实习,本来是想留下的,奈何HC冻结,入职时候,面试我的主管大佬已经离职了,在那里20多天,很佛系的点点扫描器,改改之前留的bug之类的,混了一个团建。算是初步了解了一下互联网公司的工作模式和方法。不得不说,虽然没有下午茶之类的,但提供抽纸是很实在的,省得自己带卫生纸……

第三家是秋招时候佛系投的,没想到中了。目前在这里实习,整个团队都很年轻,0.8的同事都是95后,leader也是90后。在年轻的团队好处还是挺多的,能够接触不少项目,同事之间也少有70/80后那种比较官僚的样子。

------------------------------------------------------

在大三时候就纠结,做安全到底是在甲方好,还是在乙方好,看到一个老哥回答说,“核心问题不在于甲方乙方,在于在哪里有优秀的人,在哪里能够有很大的提升”。我最后选择甲方的原因有以下几点,

【a】技术方面甲方团队不一定比乙方差,甚至大甲方比乙方还6。因此“乙方”更锻炼技术的说法虽然有一定的道理,但不可以作为绝对的参考标准。

【b】自己真的喜欢技术吗?众所周知,如果去乙方,职业路径的很长一段时间都是和攻防技术/漏洞研究打交道,而在甲方,很可能慢慢转风控,业务安全等方向。那么我真的喜欢技术吗,到底自己期望的职业路径是什么呢。我最终是想投入到互联网公司的怀抱的,因为互联网的数据量,业务需求等都是一线的,且经过第二家公司的实习,认为自己更适合互联网公司。那么问题就转变为了,经过了XXXX的工作经验,我最终去了互联网甲方。所以XXXX刚毕业第一份工作,是乙方还是甲方呢?

【c】发现咨询别人也会各有角度,乙方的同事会说乙方锻炼技术,体系全面;互联网公司的同事会说,最终想去互联网公司,其实一开始就在互联网公司呆着,就挺好。这就牵扯出另外一个问题,对于工作几年后跳槽(跳到互联网甲方企业)来说,是从乙方跳好呢?还是从同级别的互联网公司好呢?

对于甲方企业,可能只需要对某一方面很精通的人,而乙方出来可能对整个安全会有整体认知(对于我自己来说),但可能某一方面(比如扫描器、HIDS等)不像在甲方同学那么精通。这样来看,我就不如直接在互联网公司磨练。这个点要感谢Kevin1986大佬的指点。

【d】目前在大甲方安全团队能够成为中坚力量的,必然是在圈子里摸爬滚打了很多年的大佬们,从零几年互联网刚刚兴起的时候就开始做安全了。对于我个人来说,可能技术更重要吧,但如果有一个带你飞的人,也是人生道路上的一大幸事。

【e】钱端安全工程师,这是权重最低的一项

----------------------------------------------------------

于是我就来到了现在的公司,目前每天的工作是漏洞审核,写写web代码,未来应该会深入某一个方向去搞,比如SDL、开发、主机安全、扫描器等等,但深知自己的技术栈不够深,还是需要多多补充。

自己对内网的安全了解很少,在这里立一个flag吧,马上Q2结束Q3开始,要在Q3期间,把windows内网渗透那块学习一下。Q3结束应该是9月底,到时候回头看看这个flag…

3 生活

感情上,已经比较佛系了。但还想再挣扎一下下。有点惧怕未来之类的,GG,

别的方面…其实原本不想在北京,但只有北京能提供这么好的就业机会,前天在boss直聘上了解了一下天津网络安全行业的行情,除了几个乙方招渗透岗比较多,其他公司不怎么招安全岗,而且天津甲方的工资都比较低…

4 其他

为什么今天晚上想这么多,其实是因为想到了自己的一个小愿望,自己和自己有一个十年之约,今年是刚刚毕业的第一年,十年能把人变成什么样呢?我又该怎么做呢。

 

 

 

 

 

 

 

 

 

 

【四轴飞行器】非线性三自由度四轴飞行器模拟器研究(Matlab代码实现)内容概要:本文围绕非线性三自由度四轴飞行器模拟器的研究展开,重点介绍基于Matlab代码实现的四轴飞行器动力学建模与仿真方法。研究构建了考虑非线性特性的飞行器数学模型,涵盖姿态动力学与运动学方程,实现了三自由度(滚转、俯仰、偏航)的精确模拟。文中详细阐述了系统建模过程、控制算法设计思路及仿真结果分析,帮助读者深入理解四轴飞行器的飞行动力学特性与控制机制;同时,该模拟器可用于算法验证、控制器设计与教学实验。; 适合人群:具备一定自动控制理论基础和Matlab编程能力的高校学生、科研人员及无人机相关领域的工程技术人员,尤其适合从事飞行器建模、控制算法开发的研究生和初级研究人员。; 使用场景及目标:①用于四轴飞行器非线性动力学特性的学习与仿真验证;②作为控制器(如PID、LQR、MPC等)设计与测试的仿真平台;③支持无人机控制系统教学与科研项目开发,提升对姿态控制与系统仿真的理解。; 阅读建议:建议读者结合Matlab代码逐模块分析,重点关注动力学方程的推导与实现方式,动手运行并调试仿真程序,以加深对飞行器姿态控制过程的理解。同时可扩展为六自由度模型或加入外部干扰以增强仿真真实性。
基于分布式模型预测控制DMPC的多智能体点对点过渡轨迹生成研究(Matlab代码实现)内容概要:本文围绕“基于分布式模型预测控制(DMPC)的多智能体点对点过渡轨迹生成研究”展开,重点介绍如何利用DMPC方法实现多智能体系统在复杂环境下的协同轨迹规划与控制。文中结合Matlab代码实现,详细阐述了DMPC的基本原理、数学建模过程以及在多智能体系统中的具体应用,涵盖点对点转移、避障处理、状态约束与通信拓扑等关键技术环节。研究强调算法的分布式特性,提升系统的可扩展性与鲁棒性,适用于多无人机、无人车编队等场景。同时,文档列举了大量相关科研方向与代码资源,展示了DMPC在路径规划、协同控制、电力系统、信号处理等多领域的广泛应用。; 适合人群:具备一定自动化、控制理论或机器人学基础的研究生、科研人员及从事智能系统开发的工程技术人员;熟悉Matlab/Simulink仿真环境,对多智能体协同控制、优化算法有一定兴趣或研究需求的人员。; 使用场景及目标:①用于多智能体系统的轨迹生成与协同控制研究,如无人机集群、无人驾驶车队等;②作为DMPC算法学习与仿真实践的参考资料,帮助理解分布式优化与模型预测控制的结合机制;③支撑科研论文复现、毕业设计或项目开发中的算法验证与性能对比。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注DMPC的优化建模、约束处理与信息交互机制;按文档结构逐步学习,同时参考文中提及的路径规划、协同控制等相关案例,加深对分布式控制系统的整体理解。
当然可以!下面是 **完整、清晰、带详细注释的 Linux 内核模块代码**,实现了仅运行在 CPU0 上的 RX 调度器,支持多优先级队列,并包含高优先级包的“快速路径”直通机制。 所有关键逻辑都配有 **中文详细注释**,帮助你理解每一行的作用和设计意图。 --- ```c /* * rx_scheduler.c - 基于优先级的接收包调度器(仅用于 CPU0) * * 功能: * - 将收到的数据包按 DSCP 优先级分类 * - 高优先级包尝试立即处理(fast path),降低延迟 * - 其他包或拥塞时进入队列,由 tasklet 批量处理(slow path) * - 使用 tasklet 替代 NAPI 实现软中断延迟处理 * - 不使用 per-CPU 变量,全局单实例绑定到 CPU0 * * 编译方式: * make -C /lib/modules/$(uname -r)/build M=$(pwd) modules * 加载: * insmod rx_scheduler.ko * 卸载: * rmmod rx_scheduler */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/skbuff.h> // struct sk_buff 相关操作 #include <linux/netdevice.h> // netif_receive_skb() #include <linux/interrupt.h> // tasklet, softirq #include <linux/spinlock.h> // 自旋锁保护共享资源 #include <linux/ip.h> // ip_hdr(), ipv4_get_dsfield() /* ==================== 配置参数 ==================== */ #define MAX_PRIO_QUEUES 3 // 支持三种优先级:高、中、低 #define MAX_IMMEDIATE_RX 16 // 当高优先级队列少于该数量时,新包走 fast path /* ==================== 优先级枚举 ==================== */ enum rx_priority { PRIO_HIGH = 0, // EF ( Expedited Forwarding ) 或 CS7 等实时业务 PRIO_MEDIUM = 1, // AF 类业务,如视频流 PRIO_LOW = 2, // 默认 Best-Effort 流量 }; /* ==================== 数据结构定义 ==================== */ // 每个优先级对应一个 FIFO 队列 struct rx_prio_queue { struct sk_buff_head queue; // 内核提供的 skb 队列(双链表) spinlock_t lock; // 保护此队列的并发访问(中断安全) }; // 全局调度器状态(只运行在 CPU0 上) struct rx_scheduler { struct rx_prio_queue queues[MAX_PRIO_QUEUES]; // 三个优先级队列 bool processing; // 标志位:是否已有 tasklet 被调度(防重复唤醒) }; /* ==================== 全局变量 ==================== */ // 全局唯一的调度器实例,固定绑定到 CPU0 static struct rx_scheduler rx_sched_on_cpu0; // 延迟执行的 tasklet(将在 softirq 上下文中运行) static void rx_tasklet_handler(unsigned long data); static DECLARE_TASKLET(rx_tasklet, rx_tasklet_handler, 0); // 模块参数:是否启用调度功能(默认开启) static bool enable_rx_scheduling = true; module_param(enable_rx_scheduling, bool, 0644); MODULE_PARM_DESC(enable_rx_scheduling, "是否启用自定义 RX 调度器"); /* ==================== 函数声明 ==================== */ void receive_and_schedule(struct sk_buff *skb); EXPORT_SYMBOL(receive_and_schedule); // 导给网卡驱动调用 /* ==================== 初始化与退 ==================== */ /* * 模块初始化函数 * 在 insmod 时被调用,初始化所有数据结构 */ static int __init rx_scheduler_init(void) { int prio; pr_info("RX Scheduler (CPU0-only mode) loaded\n"); // 初始化每个优先级队列 for (prio = 0; prio < MAX_PRIO_QUEUES; prio++) { skb_queue_head_init(&rx_sched_on_cpu0.queues[prio].queue); // 初始化空队列 spin_lock_init(&rx_sched_on_cpu0.queues[prio].lock); // 初始化自旋锁 } // 初始状态:没有 tasklet 正在等待执行 rx_sched_on_cpu0.processing = false; // 启用 tasklet(虽然默认是启用的) tasklet_enable(&rx_tasklet); return 0; } /* * 模块卸载函数 * 在 rmmod 之前必须确保 tasklet 完全停止 */ static void __exit rx_scheduler_exit(void) { tasklet_disable(&rx_tasklet); // 禁止 tasklet 被调度 tasklet_kill(&rx_tasklet); // 等待正在运行的 tasklet 结束 pr_info("RX Scheduler unloaded\n"); } /* ==================== 包分类函数 ==================== */ /* * classify_packet - 根据 IP 头部 DSCP 字段对数据包进行分类 * @skb: 待分类的数据包 * * 返回值:对应的优先级(PRIO_HIGH / PRIO_MEDIUM / PRIO_LOW) * * 示例: * DSCP = 0x2E (EF) -> PRIO_HIGH * DSCP >= 0x20 -> PRIO_MEDIUM * 其他 -> PRIO_LOW */ static enum rx_priority classify_packet(struct sk_buff *skb) { // 如果 MAC 层信息未设置,无法解析上层协议 if (!skb_mac_header_was_set(skb)) goto low; // 只处理 IPv4 数据包 if (skb->protocol == htons(ETH_P_IP)) { struct iphdr *iph = ip_hdr(skb); // 获取 IP 头指针 u8 dscp = ipv4_get_dsfield(iph) >> 2; // 提取 DSCP (6 bits) if (dscp == 0x2E || dscp == 0x38) { // EF (VoIP) 或 CS7 (控制信令) return PRIO_HIGH; } else if (dscp >= 0x20) { // 如 AF41/AF42/AF43 视频流 return PRIO_MEDIUM; } } low: return PRIO_LOW; // 默认为低优先级 } /* ==================== 主入口函数 ==================== */ /** * receive_and_schedule - 网卡驱动调用的主入口函数 * @skb: 收到的数据包 * * 说明: * 这个函数通常由网卡中断上下文调用。 * 我们假设所有流量都被路由到 CPU0(通过 IRQ affinity 设置)。 * * 行为: * 1. 若禁用调度,则直接提交协议栈 * 2. 若为高优先级且队列不忙,则立即处理(fast path) * 3. 否则加入对应优先级队列,并触发 tasklet(slow path) */ void receive_and_schedule(struct sk_buff *skb) { enum rx_priority prio; // 分类后的优先级 bool defer = false; // 是否需要延迟处理(即是否要调度 tasklet) // 如果模块参数关闭了调度功能,直接交给协议栈处理 if (!enable_rx_scheduling) { netif_receive_skb(skb); return; } /* Step 1: 对数据包进行优先级分类 */ prio = classify_packet(skb); /* Step 2: 高优先级包尝试走快速路径(不进队列) */ if (prio == PRIO_HIGH) { struct rx_prio_queue *pq = &rx_sched_on_cpu0.queues[PRIO_HIGH]; unsigned long flags; // 获取锁以安全读取队列长度 spin_lock_irqsave(&pq->lock, flags); // 如果当前高优先级队列中的包少于阈值,认为系统不忙 // 直接在中断上下文中处理,减少延迟 if (skb_queue_len(&pq->queue) < MAX_IMMEDIATE_RX) { spin_unlock_irqrestore(&pq->lock, flags); netif_receive_skb(skb); // 直接提交协议栈(fast path) return; // 函数结束,不再入队 } // 否则解锁并继续走慢速路径(入队 + tasklet) spin_unlock_irqrestore(&pq->lock, flags); } /* Step 3: 将数据包加入对应优先级队列(slow path) */ // 获取目标队列的锁(注意:不同优先级使用不同的锁) spin_lock(&rx_sched_on_cpu0.queues[prio].lock); // 将 skb 添加到队列末尾 __skb_queue_tail(&rx_sched_on_cpu0.queues[prio].queue, skb); /* * 检查是否已经有一个 tasklet 在等待执行 * 如果没有(processing == false),我们就调度一个新的 tasklet * 防止重复调用 tasklet_schedule() 导致 softirq 开销过大 */ if (!rx_sched_on_cpu0.processing) { rx_sched_on_cpu0.processing = true; // 标记“已调度” defer = true; // 触发 tasklet 调度 } // 释放锁 spin_unlock(&rx_sched_on_cpu0.queues[prio].lock); /* Step 4: 触发 tasklet 进行批量处理 */ if (defer) { // 明确指定在 CPU0 上调度 tasklet(可选,但更清晰) tasklet_schedule_on_cpu(&rx_tasklet, 0); // 也可以直接用 tasklet_schedule(),它会在当前 CPU 触发 } } EXPORT_SYMBOL(receive_and_schedule); /* ==================== Tasklet 处理函数 ==================== */ /** * rx_tasklet_handler - 在 softirq 上下文中批量处理数据包 * @data: 传入的参数(此处未使用) * * 说明: * - 该函数运行在 softirq 上下文(原子上下文),不能睡眠 * - 按照 PRIO_HIGH → PRIO_MEDIUM → PRIO_LOW 的顺序队 * - 每次最多处理 64 个包,避免长时间占用 CPU * - 若仍有积压,重新调度 tasklet;否则清除 processing 标志 */ static void rx_tasklet_handler(unsigned long data) { struct sk_buff_head output_list; // 临时链表,用于收集待提交的 skb bool has_more = false; // 标志位:是否还有更多包待处理 unsigned long flags; // 初始化临时输链表(用于 netif_receive_skb_list) __skb_queue_head_init(&output_list); /* Step 1: 按优先级从高到低扫描队列 */ for (int prio = 0; prio < MAX_PRIO_QUEUES; prio++) { struct rx_prio_queue *pq = &rx_sched_on_cpu0.queues[prio]; // 获取该优先级队列的锁 spin_lock_irqsave(&pq->lock, flags); int count = 0; // 记录本次从该队列取的包数 // 每个优先级最多取 32 个包,防止某个队列垄断处理时间 while (count < 32 && !skb_queue_empty(&pq->queue)) { struct sk_buff *skb = __skb_dequeue(&pq->queue); // 取一个包 __skb_queue_tail(&output_list, skb); // 加入输列表 count++; } // 如果该队列还有剩余包,则标记“仍有积压” if (!skb_queue_empty(&pq->queue)) { has_more = true; } // 释放锁 spin_unlock_irqrestore(&pq->lock, flags); // 总共最多处理 64 个包,提前退 if (skb_queue_len(&output_list) >= 64) { break; } } /* Step 2: 决定是否需要再次调度 tasklet */ if (has_more) { // 仍有包未处理完,重新调度 tasklet 继续处理 tasklet_schedule_on_cpu(&rx_tasklet, 0); } else { // 所有队列均已清空,清除 processing 标志 // 注意:这里选择任意一个锁即可,因为 processing 是全局状态 spin_lock_irqsave(&rx_sched_on_cpu0.queues[0].lock, flags); rx_sched_on_cpu0.processing = false; spin_unlock_irqrestore(&rx_sched_on_cpu0.queues[0].lock, flags); } /* Step 3: 将收集的所有包提交给协议栈 */ if (!skb_queue_empty(&output_list)) { // 使用批量接口提升性能(比逐个调用更快) netif_receive_skb_list(&output_list); } } /* ==================== 模块元信息 ==================== */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("CPU0-only RX Scheduler with Priority Queues (no NAPI)"); // 注册模块初始化与退函数 module_init(rx_scheduler_init); module_exit(rx_scheduler_exit); ``` --- ## ✅ 注释亮点总结 | 特性 | 说明 | |------|------| | 📝 函数级注释 | 每个函数都有 `/** */` 风格说明其作用、参数、行为 | | 💬 行内注释 | 关键逻辑步骤添加解释,如锁、状态判断、队条件 | | 🔍 设计意图 | 解释为何使用 `processing`、为何限制每轮处理数量等 | | 🧩 模块化组织 | 分区明确:配置、结构体、初始化、分类、主入口、tasklet | | ⚠️ 安全提示 | 强调中断上下文限制、不能睡眠、锁的使用范围 | --- ## ✅ 如何编译和测试? 创建 `Makefile`: ```makefile obj-m += rx_scheduler.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean install: sudo insmod rx_scheduler.ko uninstall: sudo rmmod rx_scheduler ``` 然后: ```bash make sudo insmod rx_scheduler.ko dmesg | tail ``` 你应该看到: ``` RX Scheduler (CPU0-only mode) loaded ``` --- ##
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值