中间件
  • 【Linux】:线程安全 + 死锁问题

    1. 线程安全和重入问题🚀 1.1 基本概念 线程安全:就是多个线程在访问共享资源时,能够正确地执行,不会相互干扰或破坏彼此的执行结果。一般而言,多个线程并发同一段只有局部变量的代码时,不会出现不同的结果。但是对全局变量或者静态变量进行操作,并且没有锁保护的情况下,容易出现该问题。 重入:同一个函数被不同的执行流调用,当前一个流程还没有执行完,就有其他的执行流再次进入,我们称之为重入。一个函数在重入的情况下,运行结果不会出现任何不同或者任何问题,则该函数被称为可重入函数,否则,是不可重入函数。 1.2 线程安全和重入情况 🍥 学到现在,其实我们已经能理解重入其实可以分为两种情况 多线程重入函数 信号导致一个执行流重复进入函数 ① 常见的线程不安全的情况 不保护共享变量的函数 函数状态随着被调用,状态发生变化的函数 返回指向静态变量指针的函数 调用线程不安全函数的函数 ② 常见的线程安全的情况 每个线程对全局变量或者静态变量只有读取的权限,而没有写入的权限,一般来说这些线程是安全的 类或者接口对于线程来说都是原子操作 多个线程之间的切换不会导致该接口的执行结果存在二义性 ③ 常见不可重入的情况 调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的 调用了标准I/O库函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构 可重入函数体内使用了静态的数据结构 ④ 常见可重入的情况 不使用全局变量或静态变量 不使用用malloc或者new开辟出的空间 不调用不可重入函数 不返回静态或全局数据,所有数据都有函数的调用者提供 使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据 提示 :不要被上面的一系列所弄晕,其实对应概念说的都是一回事 1.3 线程安全和重入的联系区别 📌 可重入与线程安全联系 函数是可重入的,那就是线程安全的 函数是……

    SE_Wang 2025-01-03
    6 0 0
  • 常见链表专题相关算法

    找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏: 优选算法专题 目录 2. 两数相加 24.两两交换链表中的节点 143.重排链表 23.合并K个升序链表 25.K个一组翻转链表 前面我们刚刚学习数据结构时,已经刷了许多与链表相关的算法了。这里还刷一些作为补充。注意:所有与链表相关的题目都是属于模拟题。因为其会给我们提供一种模拟的思路来写。 2. 两数相加 题目: 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。 示例 1: 输入:l1 = [2,4,3], l2 = [5,6,4] 输出:[7,0,8] 解释:342 + 465 = 807. 示例 2: 输入:l1 = [0], l2 = [0] 输出:[0] 示例 3: 输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9] 输出:[8,9,9,9,0,0,0,1] 提示: 每个链表中的节点数在范围 [1, 100] 内 0 <= Node.val <= 9 题目数据保证列表表示的数字不含前导零 思路:题目是让我们把链表中的两个数相加为一个数,并将这个数也转换为链表的形式。这是一道简单的模拟题。定义一个变量记录当前位数相加的结果,存储到新的链表节点中,这里在存储时一定得是小于10的数,处理方式是:%10,经过这次处理后再 /10 即可。 代码实现: class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { // 创建虚拟头节点 ListNode head = new ListNode(-1); // 申请三个指针针对后续修改 ListNode cur1 = l1, cur2 = l2, cur = head; // 保存当前两数之和的值 int sum = 0; while (cur1 != null && cur2 != null) { // 求和 sum += cur1.val; sum += cur2.val; // 构造新节点 cur.next……

    SE_Gai 2025-01-03
    1 0 0
  • 【Linux课程学习】:第二十一弹—深入理解信号(中断,信号,kill,abort,raise,larm函数)

    一.理解OS如何得键盘有数据 信号 中断 1.1硬件中断的定义: 硬件中断是由与系统相连的外设(如磁盘、网卡、键盘、时钟等)自动产生的异步信号。这些外设通过总线将中断信号发送给中断控制器,再由中断控制器转发给CPU。每个设备或设备集都有自己的中断请求(IRQ)号,基于这个IRQ号,CPU可以将相应的请求分发到对应的硬件驱动上。 每一个硬件都有自己的中断请求号(IRQ),所以以后的中断就能区分是哪个硬件发来的,就可以让CPU去哪个硬件读取数据。 中断确实是通过电路给CPU发信号的。 1.2理解硬件中断和软件信号: 1.信号其实是在模拟硬件中断的行为,只是信号是软件层面的,中断是硬件层面的。 2.中断是通过电路进行发生的,是发给CPU的,而信号是发给进程的。 3.两者有相似性,但是层级不同。 1.3阐述中断到CPU拿到数据的全过程: 当我们键盘按下以后,键盘通过电路(高电压)向CPU的针脚发送中断信息,CPU执行操作系统保存当前进程的代码和数据,然后操作系统停下来去读取外设的内存。 二.通过系统命令向进程发信号: 2.1系统命令发生信号的方法: 通过kill -(信号编号)(进程pid):对进程发送信号 通过上面的方法就能给指定的进程发送指定的信号,下面的代码我们可以给指定的信号。 2.系统命令的预想: 我们可以让一个进程死循环,然后启动另外一个shell对该进程发送一系列的信号。或者我们可以通过对某个信号进程捕捉,然后给进程发该信号,然后去执行我们的自定义行为。有很多的中断进程的信号,我们还可以去发送其他的信号观察进程的反应情况。 #include <iostream> #include <unistd.h> #include <signal.h> void handle(int signo) { std::cout << "signo:" << signo << "系统命令" << std::endl; } int main() { //自定义SIGINT-2号信号的行为,让二……

    SE_Wang 2025-01-02
    6 0 0
  • 【Linux】进程控制,手搓简洁版shell

    1、进程创建 fork函数:从已经存在的进程中创建一个新进程。新进程为子进程,原进程为父进程。 进程调用fork,当控制转移到内核中的fork代码后,内核做: 分配新的内存块和内核数据结构给子进程 将父进程部分数据结构内容拷贝给子进程 添加子进程到系统进程列表当中 fork返回,开始调度器调度 写时拷贝 (懒拷贝,时间换空间) 数据在默认不修改的情况下是共享的,不各自拷贝一份是因为父子进程间的数据大部分是重复的,一般只有少量数据需要修改,因为各自拷贝一份浪费空间。 更新父进程页表项为只读—子进程继承—子进程写入—触发系统错误—系统触发缺页中断—系统检测—判定是否要写时拷贝—拷贝,修改,恢复权限。 创建出子进程,让子进程执行一些任务: #include <iostream> #include <vector> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <stdio.h> using namespace std; enum { OK, OPEN_FILE_ERROR }; vector<int> data; int savebegin() { string name = to_string((unsigned int)time(nullptr)); name += ".backup"; FILE *pf = fopen(name.c_str(), "w"); if (pf == nullptr) { return OPEN_FILE_ERROR; } string datastr; for (auto d : data) { datastr += to_string(d); datastr += " "; } fputs(datastr.c_str(), pf);//将拿到的数据备份到文件中 fclose(pf); return OK; } void save() { pid_t id = fork(); if (id == 0) { //子进程备份数据 int code = savebegin(); exit(code); } int status = 0; pid_t rid = waitpid(id, &status, 0); if (rid > 0) { int code = WEXITSTATUS(status);//进程退出码 if (code == 0) cout << "备份成功, exit code:" << code << endl; else cout << "……

    SE_Wang 2025-01-01
    6 0 0
  • 深入理解 Linux 文件时间戳:atime、mtime 和 ctime 的概念及应用

    在 Linux 文件系统中,每个文件和目录都包含三个时间戳属性:Access 时间 (atime)、Modify 时间 (mtime) 和 Change 时间 (ctime)。这些时间戳在文件管理、编译流程(如 Makefile)、备份与恢复等场景中扮演着重要角色。本文将详细解析这些时间戳的含义、触发条件及实际应用。 时间戳的基本概念 Access Time (atime) 含义:Access Time 表示文件或目录**上次被访问(读取)**的时间。 触发条件:任何一次读取文件内容的操作(如 cat、less)都会更新 atime。 示例: 使用 cat filename 查看文件内容后,文件的 atime 会被更新。 用途: 可以用于记录文件的最近访问时间。 系统管理员或程序可以通过 atime 分析文件的使用频率,从而决定是否清理过时的文件。 Modify Time (mtime) 含义:Modify Time 表示文件内容上次被修改的时间。 触发条件:任何修改文件内容的操作都会更新 mtime,例如编辑文件并保存。 示例: 使用 vim 修改文件内容后,文件的 mtime 会更新。 用途: 在 Makefile 中判断文件是否需要重新编译。 文件同步工具(如 rsync)常通过 mtime 判断文件是否需要同步更新。 Change Time (ctime) 含义:Change Time 表示文件的元数据(如权限、所有者、链接数)上次被修改的时间。 触发条件:当文件的元数据(而非内容)发生变化时,例如更改权限或所有者,ctime 会更新。 示例: 使用 chmod 更改文件权限后,文件的 ctime 会更新。 用途: ctime 记录了元数据的最后修改时间,适合用于审计或追踪文件权限的更改。 时间戳的区别与作用 时间戳 触发条件 示例操作 用途 atime 文件被读取时 cat filename 记录文件最近的访问时间。 mtime 文件内容被修改时 编辑并保存文件内容 用于跟踪文件内容的最后修改时间;判断是否需要重新编译。 ctime 文件元数据被修改时 chmod 644 filename 用于记录元数据(如权……

    SE_Wang 2024-12-31
    13 0 0
  • Oracle–oracle导出表结构到sql文件 ,数据库的导入导出CMD命令exp和imp、使用数据泵导入(impdp)和导出(expdp)

    1.oracle导出表结构到sql文件 需要登陆oralce用户: sqlplus 用户名/密码@实例名 SQL> set serveroutput on SQL> set long 999999 SQL> set feedback off SQL> spool temp.sql SQL> SELECT DBMS_METADATA.GET_DDL('TABLE',table_name) FROM USER_TABLES; SQL> spool off 1.数据库导出功能: 1).将数据库TEST完全导出,用户名system 密码manager 导出到D:\daochu.dmp中 exp system/manager@TEST file=d:\daochu.dmp full=y 2).将数据库中system用户与sys用户的表导出 exp system/manager@TEST file=d:\daochu.dmp owner=(system,sys) 3).将数据库中的表table1 、table2导出 exp system/manager@TEST file=d:\daochu.dmp tables=(table1,table2) 4).将数据库中的表table1中的字段filed1以"00"打头的数据导出 exp system/manager@TEST file=d:\daochu.dmp tables=(table1) query=\" where filed1 like '00%'\" 如果是导出远程数据库,需要在Test前加上ip,如system/manager@192.168.1.123/test 2.数据的导入 1).将D:\daochu.dmp 中的数据导入 orcl数据库中。 imp system/manager@127.0.0.1:1521/orcl file=d:\daochu.dmp full=y ignore=y 2).将d:\daochu.dmp中的表table1 导入 imp system/manager@TEST file=d:\daochu.dmp tables=(table1) 数据泵文件 expdp介绍 EXPDP命令行选项 1. ATTACH 该选项用于在客户会话与已存在导出作用之间建立关联.语法如下 ATTACH=[schema_name.]job_name Schema_name用于指定方案名,job_name用于指定导出作业名.注意,如果使用ATTACH选项,在命令行除了连接字符串和ATTACH选项外,不能指定任何其他选项,示例如下: Expdp scott/tiger ATTACH=scott.export_job 2. CONTENT 该选项用于指定要导出的内容.默认值为ALL CONTENT={ALL | DATA_ONLY | METADATA_ONLY} 当设置CONT……

    SE_Meng 2024-12-31
    55 0 0
  • FTP传输失败

    故障原因 FTP源、目的路径中含有空格等设备不支持的字符。 FTP服务器根目录存储空间不足。 操作步骤 FTP源、目的路径中含有空格等设备不支持的字符。设备中目录名使用的字符不可以是空格、“~” 、“*” 、“/”、 “\”、 “:” 、“'” 、“"”。 如果路径中含有空格等设备不支持的字符,请修改路径。 检查FTP服务器根目录存储空间是否不足。在FTP服务器端执行命令dir,查看FTP服务器根目录下的空闲空间。 如果存储空间已满,在用户视图下执行命令delete /unreserved删除不需要的文件。 父主题: 文件系统管理常见配置错误

    SE_YT 2024-12-30
    5 0 0
  • 如何配置流量统计功能

    假设电脑192.168.1.2在ping路由器192.168.1.1时丢包,想确认中间的交换机转发报文是否有问题,可以在交换机上做流量统计进行准确确认。   网络拓扑示例图如下:   在中间的交换机上做流量统计的步骤如下: 一、配置流量统计功能 1、从用户视图切换到系统视图 <Huawei>system-view   2、创建ACL3333匹配ping请求报文,ACL3334匹配ping响应报文 [Huawei]acl 3333 [Huawei-acl-adv-3333]rule 5 permit icmp source 192.168.1.2 0 destination 192.168.1.1 0 [Huawei-acl-adv-3333]quit [Huawei]acl 3334 [Huawei-acl-adv-3334] rule 5 permit icmp source 192.168.1.1 0 destination 192.168.1.2 0 [Huawei-acl-adv-3334]quit   3、配置流分类,引用前面配置的ACL规则 [Huawei]traffic classifier test1 [Huawei-classifier-test1] if-match acl 3333 [Huawei-classifier-test1]quit [Huawei]traffic classifier test2 [Huawei-classifier-test2] if-match acl 3334 [Huawei-classifier-test2]quit   4、配置流行为,启用计数功能 [Huawei]traffic behavior test1 [Huawei-behavior-test1]statistic enable [Huawei-behavior-test1]quit [Huawei]traffic behavior test2 [Huawei-behavior-test2]statistic enable [Huawei-behavior-test2]quit   5、配置流策略,将流分类和流行为关联 [Huawei]traffic policy test1 [Huawei-trafficpolicy-test1]classifier test1 behavior test1 [Huawei-trafficpolicy-test1]quit [Huawei]traffic policy test2 [Huawei-trafficpolicy-test2]classifier test2 behavior test2 [Huawei-trafficpolicy-test2]quit   6、在连接电脑的接口上应用流策略 [Huawei]interface GigabitEthernet 0/0/2 [Huawei-GigabitEthernet0/0/2]traffic-pol……

    SE_YT 2024-12-30
    8 0 0
  • 三招搞定!Linux文件名修改大全

    一、引言 在Linux系统中,文件名修改是一个常见且重要的操作。文件名修改可以更好地管理文件和文件夹,使其更具可读性和有序性。通过更改文件名,可以清晰地表达文件的内容和用途,便于快速识别和定位文件。此外,对文件名进行调整还有利于遵循特定的命名规则和约定,有助于项目协作和文件组织。 然而,并不是所有的用户都熟悉文件名修改的各种方法。本文将介绍三种在Linux系统下常用的文件名修改方法,分别是使用mv命令、rename命令以及结合find命令和shell脚本。通过学习这三种方法,能够轻松地处理各种不同的文件名修改需求,更好地管理自己的文件系统。 二、使用mv命令修改文件名 mv命令是Linux系统下用于移动文件或重命名文件的命令。其基本用法如下: 将文件移动到指定目录: mv <source_file> <destination_directory> 例如,将文件file1.txt移动到目录/home/fly/中: mv file1.txt /home/fly/ 将文件重命名: mv <old_file_name> <new_file_name> 例如,将文件oldfile.txt重命名为newfile.txt: mv oldfile.txt newfile.txt 一次性移动多个文件到指定目录: mv <source_file1> <source_file2> ... <destination_directory> 例如,将文件file1.txt和file2.txt一起移动到目录/home/fly/中: mv file1.txt file2.txt /home/fly/ 注意:使用mv命令将文件移动到不同的文件系统中时,实际上是在执行复制并删除源文件的操作,而不是简单的移动。 使用mv命令直接将文件移动到新的目录并且在目标位置给它一个新的名字,这样就相当于是对文件进行了重命名。 知识扩展,mv命令的一些高级用法: 批量修改文件名的前缀或后缀。假设有一批文件名以"file"开头,把它们的文件名前加上"new_"前缀: for file in file*; do mv "$file" "new_$file"; done # 首先会获取所有以"fi……

    SE_Wang 2024-12-30
    12 0 0
  • 【Linux】:多线程(读写锁 && 自旋锁)

    1. 读写锁 🔏 1.1 基本概念 🔥 读写锁(Read-Write Lock)是一种用于多线程环境下同步访问共享资源的锁。它与传统的互斥锁(Mutex)有所不同,提供了更细粒度的控制,以便提高并发性能。它允许多个线程同时 读取 数据,但在写入数据时,必须确保只有一个线程可以进行写操作,并且在写操作期间,所有的读操作都必须等待。 💧 读写锁的核心思想是:读操作之间是可以并发执行的,而写操作是独占的,即不能与其他读操作或者写操作同时执行 1.2 读写锁的工作原理及特点 即读锁允许多个线程同时获得,因为读操作本身是线程安全的;而写锁则是互斥锁,不允许多个线程同时获得写锁,并且写操作和读操作也是互斥的 🐇 读写锁的特点: 读读不互斥:多个读线程可以同时访问共享资源 读写互斥:读操作和写操作互斥,即在写操作进行时,其他线程不能进行读或写操作 写写互斥:多个写线程不能同时进行写操作 🐇 具体来说,读写锁的行为如下: 读操作(共享锁): 如果没有线程正在持有写锁,那么多个线程可以同时获得读锁并执行读取操作。 读操作不会阻塞其他读操作,但会阻塞写操作。 写操作(独占锁): 写操作会阻塞所有其他的读操作和写操作。换句话说,在某个线程持有写锁期间,其他线程既无法获得读锁也无法获得写锁。 写操作是独占的,确保在操作过程中共享数据的一致性 1.3 读写锁的实现 🥝 读写锁相关函数 在书写具体代码之前,我们先来了解一下其相关函数 ① 初始化锁 原型: int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); 参数: rwlock: 指向 pthread_rwlock_t 类型的读写锁对象的指针。 attr: 一个指向 pthread_rwlockattr_t 类型的指针,可以设置锁的属性。 如果不需要特定的属性,通常可以将其设置为 NULL。 返回值: 返回 0 表示成功,返回错误码(如 EINVAL)表示初始化失……

    SE_Wang 2024-12-27
    6 0 0