【Linux系统编程(十五)】信号量

2023-05-16

文章目录

  • 信号量
    • 1 信号量
      • 1.1 信号量的概述
      • 1.2 信号量的API
        • 1.2.1 初始化信号量
        • 1.2.2 信号量减一(P操作)
        • 1.2.3 尝试对信号量减一
        • 1.2.4 信号量加一(V操作)
        • 1.2.5 销毁信号量
      • 1.3 代码示例
        • 1.3.1 信号量用于线程的互斥
        • 1.3.2 信号量用于线程的同步
    • 2 无名信号量用于有血缘关系的进程间互斥与同步
      • 2.1 代码示例
        • 2.1.1 无名信号量用于有血缘关系的进程间互斥
        • 2.1.2 无名信号量用于有血缘关系的进程间同步
    • 3 有名信号量用于无血缘关系的进程间互斥与同步
      • 3.1 有名信号量的API
        • 3.1.1 创建一个有名信号量
        • 3.1.2 信号量的关闭
        • 3.1.3 信号量文件的删除
      • 3.2 代码示例
      • 3.2.1 有名信号量用于无血缘关系的进程间互斥
      • 3.2.2 有名信号量用于无血缘关系的进程间同步

信号量

1 信号量

1.1 信号量的概述

信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于0时,则可以访问,否则将阻塞。PV原语是对信号量的操作,一次Р操作使信号量减1,一次V操作使信号量加1。信号量主要用于进程或线程间的同步和互斥这两种典型情况。
信号量数据类型为: sem_t

信号量用于互斥:

不管多少个任务互斥,只需要一个信号量。先P操作,再V操作

在这里插入图片描述

信号量用于同步:

有多少个任务,就需要多少个信号量。最先执行的任务对应的信号量为1,其他信号量全部为0。
执行任务时,先P执行任务,执行完再V下一个执行任务

在这里插入图片描述

1.2 信号量的API

1.2.1 初始化信号量

创建一个信号量并初始化它的值。一个无名信号量在被使用前必须先初始化

#include <semaphore.h>

int sem_init(sem_t *sem, int pshared, unsigned int value)

参数:
	sem:信号量的地址
	pshared:等于0,信号量在线程间共享(常用);
			 不等于0,信号量在进程共享。
	value:信号量的初始值

返回值:
	成功:0
	失败:-1

1.2.2 信号量减一(P操作)

将信号量减一,如果信号量的值为0则阻塞,大于0可以减一

#include <semaphore.h>

int sem_wait(sem_t *sem);

参数:
	sem:信号量的地址

返回值:
	成功:0
	失败:-1

1.2.3 尝试对信号量减一

尝试将信号量减一,如果信号量的值为0,不阻塞,立即返回,大于0可以减一

#include <semaphore.h>

int sem_trywait(sem_t *sem);

参数:
	信号量的地址

返回值:
	成功:0
	失败:-1

1.2.4 信号量加一(V操作)

将信号量加一

#include <semaphore.h>

int sem_post(sem_t *sem);

参数:
	信号量的地址

返回值:
	成功:0
	失败:-1

1.2.5 销毁信号量

销毁信号量

#include <semaphore.h>

int sem_destroy(sem_t *sem);

参数:
	信号量的地址

返回值:
	成功:0
	失败:-1

1.3 代码示例

1.3.1 信号量用于线程的互斥

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

//定义一个信号量(用于互斥)
sem_t sem;

void my_printf(char *str)
{
	int i = 0;
	while(str[i] != '\0')
	{
		printf("%c", str[i++]);
		fflush(stdout);
		sleep(1);
	}
	return NULL;
}

void *task_fun01(void *arg)
{
	// P 操作
	sem_wait(&sem);
	
	my_printf((char *)arg);

	// V 操作
	sem_post(&sem);
	
	return NULL;
}

void *task_fun02(void *arg)
{
	// P 操作
	sem_wait(&sem);
	
	my_printf((char *)arg);

	// V 操作
	sem_post(&sem);
	
	return NULL;
}

void *task_fun03(void *arg)
{
	// P 操作
	sem_wait(&sem);
	
	my_printf((char *)arg);

	// V 操作
	sem_post(&sem);
	
	return NULL;
}

int main(int argc, char const *argv[])
{
	//信号量初始化为1,第二参数0表示用于线程
	sem_init(&sem, 0, 1);
	
	pthread_t tid1, tid2, tid3;
	
	pthread_create(&tid1, NULL, task_fun01, "hello");
	pthread_create(&tid2, NULL, task_fun02, "world");
	pthread_create(&tid3, NULL, task_fun03, "beijing");
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	pthread_join(tid3, NULL);
	
	//销毁信号量
	sem_destroy(&sem);
	
	return 0;
}

在这里插入图片描述


1.3.2 信号量用于线程的同步

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

//定义三个信号量(用于同步)
sem_t sem1;
sem_t sem2;
sem_t sem3;

void my_printf(char *str)
{
	int i = 0;
	while(str[i] != '\0')
	{
		printf("%c", str[i++]);
		fflush(stdout);
		sleep(1);
	}
	return NULL;
}

void *task_fun01(void *arg)
{
	// P 操作
	sem_wait(&sem1);
	
	my_printf((char *)arg);

	// V 操作
	sem_post(&sem2);
	
	return NULL;
}

void *task_fun02(void *arg)
{
	// P 操作
	sem_wait(&sem2);
	
	my_printf((char *)arg);

	// V 操作
	sem_post(&sem3);
	
	return NULL;
}

void *task_fun03(void *arg)
{
	// P 操作
	sem_wait(&sem3);
	
	my_printf((char *)arg);

	// V 操作
	sem_post(&sem1);
	
	return NULL;
}

int main(int argc, char const *argv[])
{
	//信号量初始化,第二参数0表示用于线程
	sem_init(&sem1, 0, 1);
	sem_init(&sem2, 0, 0);
	sem_init(&sem3, 0, 0);
	
	pthread_t tid1, tid2, tid3;
	
	pthread_create(&tid1, NULL, task_fun01, "hello");
	pthread_create(&tid2, NULL, task_fun02, "world");
	pthread_create(&tid3, NULL, task_fun03, "beijing");
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	pthread_join(tid3, NULL);
	
	//销毁信号量
	sem_destroy(&sem1);
	sem_destroy(&sem2);
	sem_destroy(&sem3);
	
	return 0;
}

在这里插入图片描述

2 无名信号量用于有血缘关系的进程间互斥与同步

使用mmap完成无名信号量的定义

2.1 代码示例

2.1.1 无名信号量用于有血缘关系的进程间互斥

#include <stdio.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/mman.h> 

void my_printf(char *str)
{
	int i = 0;
	while(str[i] != '\0')
	{
		printf("%c", str[i++]);
		fflush(stdout);
		sleep(1);
	}
	return NULL;
}



int main(int argc, char const *argv[])
{
	//定义一个无名信号量
																//MAP_ANONYMOUS匿名映射     -1不需要文件描述符
	sem_t *sem = mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
	
	//无名信号量的初始化,参数2中的1表示进程,参数3中的1表示初始化值为1
	sem_init(sem, 1, 1);	

	pid_t pid = fork();
	if(pid == 0)//子进程
	{
		// P 操作
		sem_wait(sem);
		
		my_printf("hello");
		
		// V 操作
		sem_post(sem);
	}
	else if(pid > 0)//父进程
	{
		// P 操作
		sem_wait(sem);
		
		my_printf("world");
		
		// V 操作
		sem_post(sem);
	}

	//销毁信号量
	sem_destroy(sem);
	
	return 0;
}

在这里插入图片描述


2.1.2 无名信号量用于有血缘关系的进程间同步

#include <stdio.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/mman.h> 

void my_printf(char *str)
{
	int i = 0;
	while(str[i] != '\0')
	{
		printf("%c", str[i++]);
		fflush(stdout);
		sleep(1);
	}
	return NULL;
}



int main(int argc, char const *argv[])
{
	//定义一个无名信号量
																//MAP_ANONYMOUS匿名映射     -1不需要文件描述符
	sem_t *sem1 = mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
	sem_t *sem2 = mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
	
	//无名信号量的初始化,参数2中的1表示进程,参数3中的1表示初始化值为1
	sem_init(sem1, 1, 1);	
	sem_init(sem2, 1, 0);

	pid_t pid = fork();
	if(pid == 0)//子进程
	{
		// P 操作
		sem_wait(sem1);
		
		my_printf("hello");
		
		// V 操作
		sem_post(sem2);
	}
	else if(pid > 0)//父进程
	{
		// P 操作
		sem_wait(sem2);
		
		my_printf("world");
		
		// V 操作
		sem_post(sem1);
	}

	//销毁信号量
	sem_destroy(sem1);
	sem_destroy(sem2);
	
	return 0;
}

在这里插入图片描述

3 有名信号量用于无血缘关系的进程间互斥与同步

3.1 有名信号量的API

3.1.1 创建一个有名信号量

创建一个有名信号量

#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>

情况一:信号量存在
sem_t *sem_open(const char *name, int oflag);

情况二:信号量不存在
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);

参数:
	name:信号量的名字
	oflag:sem_open函数的权限标志
	mode:文件权限(可读、可写、可执行0777)的设置
	value:信号量的初始值

返回值:
	成功:信号量的地址
	失败:SEM_FALIED

3.1.2 信号量的关闭

关闭信号量

#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>

int sem_close(sem_t *sem);

参数:
	信号量的地址

返回值:
	成功:0
	失败:-1

3.1.3 信号量文件的删除

删除信号量的文件

#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>

int sem_unlink(const char *name);

参数:
	信号量的文件名

返回值:
	成功:0
	失败:-1

3.2 代码示例

3.2.1 有名信号量用于无血缘关系的进程间互斥

进程A

#include <stdio.h>
#include <semapore.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

void my_printf(char *str)
{
	int i = 0;
	while(str[i] != '\0')
	{
		printf("%c", str[i++]);
		fflush(stdout);
		sleep(1);
	}
	return NULL;
}

int main(int argc, char const *argv[])
{
	//创建一个有名信号量 sem_open
	sem_t *sem = sem_open("sem", O_RDWR|O_CREAT, 0666, 1);

	// P 操作
	sem_wait(sem);
	
	//任务
	my_printf("hello world");

	// V 操作
	sem_post(sem);

	//关闭信号量
	sem_close(sem);
	
	//销毁信号量
	sem_destroy(sem);
	
	return 0;
}

进程B

#include <stdio.h>
#include <semapore.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

void my_printf(char *str)
{
	int i = 0;
	while(str[i] != '\0')
	{
		printf("%c", str[i++]);
		fflush(stdout);
		sleep(1);
	}
	return NULL;
}

int main(int argc, char const *argv[])
{
	//创建一个有名信号量 sem_open
	sem_t *sem = sem_open("sem", O_RDWR|O_CREAT, 0666, 1);

	// P 操作
	sem_wait(sem);
	
	//任务
	my_printf("beijing 2022");

	// V 操作
	sem_post(sem);

	//关闭信号量
	sem_close(sem);
	
	//销毁信号量
	sem_destroy(sem);
	
	return 0;
}

在这里插入图片描述


3.2.2 有名信号量用于无血缘关系的进程间同步

进程A

#include <stdio.h>
#include <semapore.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

void my_printf(char *str)
{
	int i = 0;
	while(str[i] != '\0')
	{
		printf("%c", str[i++]);
		fflush(stdout);
		sleep(1);
	}
	return NULL;
}

int main(int argc, char const *argv[])
{
	//创建两个有名信号量
	sem_t *sem1 = sem_open("sem1", O_RDWR|O_CREAT, 0666, 1);
	sem_t *sem2 = sem_open("sem2", O_RDWR|O_CREAT, 0666, 0);

	// P 操作
	sem_wait(sem1);
	
	//任务
	my_printf("hello world");

	// V 操作
	sem_post(sem2);

	//关闭信号量
	sem_close(sem1);
	sem_close(sem2);
	
	//销毁信号量
	sem_destroy(sem1);
	sem_destroy(sem2);
	
	return 0;
}

进程B

#include <stdio.h>
#include <semapore.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

void my_printf(char *str)
{
	int i = 0;
	while(str[i] != '\0')
	{
		printf("%c", str[i++]);
		fflush(stdout);
		sleep(1);
	}
	return NULL;
}

int main(int argc, char const *argv[])
{
	//创建两个有名信号量 sem_open
	sem_t *sem1 = sem_open("sem1", O_RDWR|O_CREAT, 0666, 1);
	sem_t *sem2 = sem_open("sem2", O_RDWR|O_CREAT, 0666, 0);

	// P 操作
	sem_wait(sem2);
	
	//任务
	my_printf("beijing 2022");

	// V 操作
	sem_post(sem1);

	//关闭信号量
	sem_close(sem1);
	sem_close(sem2);
	
	//销毁信号量
	sem_destroy(sem1);
	sem_destroy(sem2);
	
	return 0;
}

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Linux系统编程(十五)】信号量 的相关文章

  • 死锁的四个必要条件

    死锁产生的四个必要条件 互斥条件 xff1a 资源是独占的且排他使用 xff0c 进程互斥使用资源 xff0c 即任意时刻一个资源只能给一个进程使用 xff0c 其他进程若申请一个资源 xff0c 而该资源被另一进程占有时 xff0c 则申
  • 线程安全与可重入函数的区别

    线程安全 xff1a 一般来讲就是一个代码块被多个并发线程反复调用时会一直产生正确的结果 如何确保线程安全 xff1a 确保线程安全 主要 考虑线程之间共享变量的安全 xff0c 每个线程私有的内容包括 xff1a 线程id xff0c e
  • Linux模拟实现sleep

    工作原理 linux中的sleep函数能够让程序休眠一定的秒数 xff0c 到时间后自动恢复运行 实现思路 设定睡眠的秒数 睡眠 xff08 挂起 xff09 恢复运行实现机制 设定睡眠的秒数 xff1a 采用alarm 函数设定需要睡眠的
  • 基于ESP32C3处理器创建Hello World工程-并使用OpenOCD进行Debug

    1 编程环境 1 1 硬件 序号 名称 描述 备注 1 ESP C3 12F KIT 深圳安信可开发的基于其自家ESP C3 12F模块的开发板 淘宝购买 2 ESP Prog 乐鑫官方推出基于FT2232HL接口芯片的JTAG调试器 淘宝
  • 平衡二叉树旋转详解

    平衡二叉树的定义 xff08 AVL xff09 定义 平衡二叉树或者是一棵空树 xff0c 或者满足以下的性质 xff1a 它的左子树和右子树的高度之差的绝对值不超过1 xff0c 并且左子树和右子树也是一个平衡二叉树 平衡因子 左子树高
  • Linux进程组,作业,会话,作业控制详解

    进程组 xff08 1 xff09 每个进程除了有一个进程id之外还属于进程组 xff0c 进程组是一个或者多个进程的集合 xff0c 通常 xff0c 他们与同一作业相关联 xff0c 可以接收来自同一终端的各种信号 xff08 2 xf
  • 如何写一个linux精灵进程

    什么是精灵进程 精灵进程也称守护进程 xff08 Daemon xff09 xff1a 是运行在后台的一种特殊进程 xff0c 它独立于控制终端并周期性的执行某种任务 xff0c 或等待处理某些发生的事件 Linux大多数服务器就是用精灵进
  • TCP的四种定时器

    TCP使用的四种定时器 xff08 Timer xff09 重传计时器 xff08 Retransmission Timer xff09 坚持计时器 xff08 Persistent Timer xff09 保活计时器 xff08 keep
  • Linux进程池与线程池以及线程池的简单实现

    通过动态创建子进程 xff08 或者子线程 xff09 来实现并发服务器的 这样做有如下缺点 xff1a 1 动态创建进程 xff08 或线程 xff09 是比较耗费时间的 xff0c 这将导致较慢的客户响应 2 动态创建的子进程 xff0
  • linux下vim中多行注释和删除多行注释

    多行注释 xff1a a 按下Ctrl 43 v xff0c 进入列模式 b 在行首选择需要注释的行 c 按下 I xff0c 进入插入模式 xff1b d 然后输入注释符 xff08 等 xff09 e 按下 Esc 键 删除多行注释 x
  • socket编程以及select、epoll、poll示例详解

    socket编程 socket这个词可以表示很多概念 xff0c 在TCP IP协议中 IP地址 43 TCP或UDP端口号 唯一标识网络通讯中的一个进程 xff0c IP 43 端口号 就称为socket 在TCP协议中 xff0c 建立
  • 命令替换的两种方式$()和``

    命令替换的含义 命令替换是指将命令的输出作为命令替换的位置的文本 命令替换的一般作用是抽取一个命令的输出 然后使用 61 操作赋值到一个变量供以后使用 命令替换的两种方式 1 反引号 xff0c 电脑键盘Esc下面的那个键 使用如下图 xf
  • Linux中eval命令

    eval命令的作用 eval命令会首先扫描命令进行所有的替换 xff0c 然后在执行所有的命令 xff0c 该命令适用于那些一次扫描无法实现其功能的变量 xff0c 该命令对变量进行两次扫描 xff0c 这些需要进行两次扫描的变量被称为复杂
  • Shell脚本实现带颜色进度条

    最近刚刚学习啦shell脚本的编程方法 xff0c 就采用shell脚本实现了一个带颜色的进度条 xff0c 下面将结果展示给大家 程序结果 实现这个其实非常的简单 xff0c 只需要了解一些基本的语法就可以了 进度条的实现就是循环加输出格
  • KiCAD绘制原理图的几个常用的操作之一

    摘要 在绘制原理图的的过程中 xff0c 会用到很多的操作功能 xff0c 今天就介绍几个在绘制原理图时必须要用到的几个功能 xff1a 1 放置原理图符号 xff1b 2 放置电源符号 xff1b 3 绘制器件引脚之间的连线 xff1b
  • linux中crond服务与crontab用法详解

    crond服务 crond服务是一种守护进程 xff0c 用来定期执行程序 xff0c 安装完成系统之后 xff0c 默认便会启动此任务调度命令 crond命令每分钟会定期检查是否有要执行的工作 xff0c 如果有要执行的工作便会自动执行该
  • shell字符串截取方法

    运算符截取 1 和 截取字符串 xff08 删左边留右边 xff09 下面我们先看代码和运行结果 解释 xff1a span class hljs keyword var span span class hljs keyword strin
  • 面试题:判断一个节点是否在一棵二叉树中

    题目 xff1a 判断一个节点是否在一棵二叉树中 结点定义如下 span class hljs keyword struct span BinaryTree BinaryTree span class hljs keyword char s
  • shell脚本实现希尔(shell)排序

    题目 xff1a 采用shell脚本实现希尔排序 最近刚刚学习啦shell脚本编程 xff0c 因此写了一个简单的希尔排序 span class hljs shebang bin bash span arr 61 span class hl
  • Linux小项目-群聊系统

    项目名称 xff1a chat room群聊系统背景知识与主要技术 xff1a 熟悉Linux基本指令的使用 xff08 ls cd make mkdir top basename pwd cp mv rm touch xff09 熟悉li

随机推荐

  • 求先递增在递减数组中的最大值

    题目 xff1a 一个数组先从小到大递增在从大到小递减 xff0c 找出数组的最大值 思路 xff1a 可以依次遍历整个数组如果array i 满足array i gt array i 1 amp amp array i gt array
  • 哈希(HASH)冲突的处理方法

    通过构造良好的哈希函数可以减少冲突 xff0c 但一般不能完全避免冲突 因此解决冲突是哈希法的另一个关键问题 常用的解决冲突方法有以下四种 开放地址法 这种方法也称再散列法 xff0c 基本思想是当关键字key的哈希地址p 61 H key
  • 消息队列实现从一个进程向另一个进程发送一个数据块的方法

    首先是Comm h的代码 include lt stdio h gt include lt string h gt include lt sys types h gt include lt sys ipc h gt include lt s
  • 打开PADS出现“PADS已停止工作”提示的解决办法

    一 场景 前一天还可以正常使用 xff0c 今天处理完一些事务后点击PADS打算画一些PCB xff0c 结果弹窗出现 PADS已停止工作 xff0c 无论是打开PADS的Logic还是Layout文件都提示这个 xff0c 打开其他之前正
  • cmake解决动态库soname,rpath以及符号冲突解决方案备忘

    set target properties TGT PROPERTIES NO SONAME TRUE SKIP BUILD RPATH TRUE LINK OPTIONS 34 Wl version script 61 CMAKE CUR
  • KiCAD绘制原理图---------创建一个新的原理图符号

    1 创建一个新的原理图库文件 第1步 xff0c 打开原理图器件编辑界面 如图1 1 1所示 xff0c 点击 Smbol Editor 图标进入器件编辑界面 第2步 xff0c 进入文件管理菜单 如图1 2 1所示 xff0c 点击 Fi
  • ubuntu 查看内存命令

    Linux中使用free 可以查看系统内存使用状态 默认单位为KB 为单位 xff0c 在此我以MB为单位说明 lostman 64 lostman MS 6702E 桌面 free m total used free shared buf
  • Nvidia Xavier Nx平台SD卡热插拔检测失效问题调试记录

    1 前言 Xaiver NX上 使用sdmmc3为sd卡 正常工作 但是 当热插拔时会检测不到 使用GPIO12 GPIO3 PCC 04 作为cd gpio cd gpios lt amp tegra aon gpio TEGRA194
  • MobaXterm连接虚拟机超时:Connection timed out

    折腾了几个小时 来两句废话 1 首先我确认了虚拟机防火墙已关 2 ip配置无问题 3 重置VMware网络设置啥的 然而并没有卵用 4 虚拟机ping百度正常 主机ping虚拟机正常 以上4条依然无效 解决方案 原理不清楚 但是解决了 通过
  • Windows下python激活虚拟环境后仍然使用全局python和pip

    这么过分一定要发CSDN jpg 在windows下 xff0c 激活python虚拟环境后 xff0c 使用的python和pip仍然是全局的python和pip 如图 使用pip list 可以看到这个包这么多 xff0c 显然不是我刚
  • openmv 自学笔记(APRILTAG标记追踪)

    由图可知 id 为5 旋转角度 为11 0 左边旋转 角度增加 正式时候调度接近0 右边旋转 角度减少 由360度 向右减少 Tx 在左边的时候 为负数 右边为正值 Ty 在上边的时候为正数 左边为负值 Tz 从远处 到近处 由负数到向正数
  • 学习STM32(3)-电源、时钟、复位电路

    Stm32 时钟分析 该分析材料大部分来自opendev 论坛 xff0c 我所做的只不过是加上一些自己的分析和整理 xff0c 由于个人能力有限 xff0c 纰漏之处在所难免 xff0c 欢迎指正 一 硬件上的连接问题 如果使用内部RC振
  • 只是运行roslauch来发布一次TF

    如果只是希望运行roslaunch来发布一次TF xff0c 可以使用launch文件中的node标签来实现 下面是一个发布一次TF的launch文件例子 xff1a lt launch gt lt node pkg 61 34 tf2 r
  • 2019年年终总结(流水账)

    2019年年终总结 流水账 前言 马上就要是2020年了 xff0c 我此时敲下我的第一篇年终总结 马上就要过去的2019年对于我来说是平凡但却不平淡的一年 xff0c 这一年里我经历了很多 xff0c 虽然这些在别人眼中可能是微不足道的
  • 融资租赁与经营租赁的区别

    我现在手上项目的客户是一家销售公司 xff0c 他们有把自己的商品租赁给别的公司经营的业务 于是就有了上面的融资租赁与经营租赁 xff0c 这两种方式在财务上对资产的处理是不一样的 下面我们来看看这个场景 xff1a A公司把资产租给B公司
  • 【Linux网络编程(五)】TCP编程流程

    文章目录 TCP编程1 TCP介绍 编程流程2 TCP C S架构3 TCP客户端编程流程1 创建TCP套接字2 connect连接服务器3 send发送请求4 recv接收应答 xff08 默认带阻塞 xff09 5 close6 客户端
  • ESP32-Drone四旋翼无人机代码编译发现的二个问题及解决方法

    摘要 ESP32 Drone四旋翼无人机是乐鑫的一个开源项目 xff0c 我根据官方的硬件参考设计 xff0c 重新使用KiCAD绘制了原理图和PCB板 xff0c 并制作了控制板样板 xff0c 在配置了ESP idf 4 4编程环境编译
  • 小觅相机运行vins-mono

    小觅相机运行vins mono span class token function mkdir span p mynt eye vins catkin ws src span class token function cd span myn
  • 程序员改变世界,从未如此直观

    万万没想到 xff0c 包博士的代码让一个六岁的小学生哇哇大哭 这个让小学生流眼泪的 科学家代表 有非常漂亮的履历 xff1a 清华大学毕业 博士曾在斯坦福就读 xff0c 他现在是VIPKID的首席AI科学家 xff0c 带领四十多人的产
  • 【Linux系统编程(十五)】信号量

    文章目录 信号量1 信号量1 1 信号量的概述1 2 信号量的API1 2 1 初始化信号量1 2 2 信号量减一 xff08 P操作 xff09 1 2 3 尝试对信号量减一1 2 4 信号量加一 xff08 V操作 xff09 1 2