简明linux系统编程--互斥锁--TCP--UDP初识

目录

1.互斥锁

2.信号

2.1介绍

2.2信号的内核机制

3.linux网络编程概述

3.1一览七层协议

3.2一览数据传输过程

 3.3四层网络模型

3.4服务端和客户端的数据交互

4.TCP服务端编程

5.TCP客户端编程

6.UDP服务端编程

7.UDP客户端编程


1.互斥锁

互斥锁也是和信号量一样,用于进行任务之间的通信

我们的这个互斥锁,分为上锁和解锁,我们的某一个进程占用这个资源的时候,就会把这个共享区域上锁,表示这个空间资源已经被使用,其他的想要使用这个资源的进程就会被挂起,直到我们的这个正在使用资源的进程使用完毕,其他的被挂起的进程才可以使用这个资源,这个资源就会被从原来的上锁状态到现在的解锁状态,被其他的进程使用;

实际上这个互斥锁主要是是被线程使用,互斥锁不可能会同时被两个线程拥有,我们把这个称之为排他性;

已经处于加锁的状态的互斥锁,被其他的线程访问,这个线程就会被加锁,只有这个互斥锁解锁的时候,其他的线程才可以使用;

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <semaphore.h>//两个线程函数的声明
void *thread1_function(void *arg);
void *thread2_function(void *arg);pthread_mutex_t mutex;//创建互斥锁//主函数进行互斥锁的创建和初始化,以及线程的创建
int main(void)
{pthread_t pthread1, pthread2;int ret;//初始化互斥锁//第二个就是默认的配置选项pthread_mutex_init(&mutex, NULL);ret = pthread_create(&pthread1, NULL, thread1_function, NULL);if(ret != 0){perror("pthread_create");exit(1);}ret = pthread_create(&pthread2, NULL, thread2_function, NULL);if(ret != 0){perror("pthread_create");exit(1);}//线程的连接,第一个参数就是连接线程的线程号pthread_join(pthread1, NULL);pthread_join(pthread2, NULL);printf("The thread is over, process is over too.\n");return 0;
}//线程1的操作:上锁
void *thread1_function(void *arg)
{int i;while(1){//这个函数就是对于这个进行初始化的互斥锁进行上锁pthread_mutex_lock(&mutex);for(i = 0; i < 10; i++){printf("Hello world\n");sleep(1);}//循环休眠之后进行解锁的操作pthread_mutex_unlock(&mutex);sleep(1);}return NULL;
}//线程2的操作:先是阻塞挂起,然后加锁(线程1已经占用完成)
void *thread2_function(void *arg)
{int i;//确保线程1先运行,开始的时候让这个线程1先运行sleep(1);while(1){//尝试加锁,但是会处于阻塞状态pthread_mutex_lock(&mutex);for(i = 0; i < 10; i++){//这个就是线程1使用完之后,才会打印这个good morningprintf("Good moring\n");sleep(1);}pthread_mutex_unlock(&mutex);sleep(1);}return NULL;
}

2.信号

2.1介绍

数据传输方式:管道,共享内存,消息队列;

信号主要用途:传递控制命令,主要是进程和应用程序之间,或者是应用程序之间;

2.2信号的内核机制

其实这个信号我们经常使用,只不过这次是说出了他的真正的名字,我们之前使用的这个ctrl+c就是退出这个程序,ctrl+z就是强制退出,这些都是我们的信号;

我们的这个信号有的是我们自己可以控制的,有的就是属于内核层面上面的,是固定的,即使我们进行自定义,他也不会按照我们的定义去修改;

下面的这个就是我们传递命令行参数,通过这个kill函数控制第二个程序里面运行的线程,我们的这个kill函数里面的传递的这个内容就是相当于信号,控制这个function里面的线程的执行;

int main(int argc, char *argv[])
{kill(atoi(argv[1]), SIGQUIT);return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>void function(int signo);int main(void)
{int i = 0;printf("pid = %d\n", getpid());signal(SIGINT, function);signal(SIGKILL, function);while(1){printf("Count to %d\n", ++i);sleep(1);}return 0;
}void function(int signo)
{//把ctrl+c的这个处理机制重写了if(signo == SIGINT){printf("You have just triggered a ctrl+c operation.\n");exit(1);}else if(signo == SIGQUIT)printf("Trig a SIGQUIT signal.\n");
}

有些时候,我们传递这个信号的时候,这个控制程序并不会按照我们的这个设计输出打印结果,例如这个,我们虽然指定了这个信号的打印结果,但是如果这个信号是内核层面的,我们就无法进行修改,这个时候打印的时候就不会按照我们的设计进行打印,而是按照系统的内核设计;

3.linux网络编程概述

3.1一览七层协议

3.2一览数据传输过程

发送就是封装的过程,接收数据就是解封的过程,类似于我们的这个快递的传输过程,发送这个快递的时候需要不断的进行打包,当我们取到这个快递的时候就需要不断地进行包装的拆解;

这个里面的主机A就相当于这个快递发送端,这个主机B就相当于这个我们对于这个数据进行拆解的过程;

 3.3四层网络模型

下面的这个四层模型就是上面的这个模型简化之后得到的:

TCP协议面向连接,建立连接之后,这个内容才会被发送,稳定传输数据;

UDP不是面向连接的,不稳定,不可靠,可能发送端和接收端没有建立连接,这个数据就会被发送出去了;

TCP因为确认连接的过程繁琐,传输的效率很低,UDP的传输效率相对较高,我们需要根据我们的具体需求进行选择;

当我们发送的数据比较大的时候,就是使用的UDP协议,例如看视频,顶多出现卡顿现象;

如果我们需要确保接收端收到数据,我们需要使用更加安全的TCP;

3.4服务端和客户端的数据交互

4.TCP服务端编程

#include <stdio.h>//下面的两个头文件是使用socket函数需要包含的
#include <sys/types.h>
#include <sys/socket.h>//htons函数需要包含下面的这个头文件
#include <arpa/inet.h>#include <netinet/in.h>
#include <unistd.h>#define PORT_ID	8800
#define SIZE	100int main(void)
{int sockfd, client_sockfd;//这个结构体的struct sockaddr_in my_addr, client_addr;int addr_len;char welcome[SIZE] = "Welcome to connect to the sever!";//1.socket()创建用于通信的节点,返回节点的描述符-----------------------------------------------------//第一个参数配置通信域//AF_INET表示我们使用的是IPV4标准//SOCK_STREAM表示的就是TCP协议的套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);//2.bind()---------------------------------------------------------------------------------------my_addr.sin_family = AF_INET;//设置端口号,应用层上面的,这个时候,//因为计算机和网络的大小端可能不统一,//我们使用这个htons函数把主机和网络的字节序进行转换统一(全部转换为大端模式)my_addr.sin_port = htons(PORT_ID);//INADDR_ANY参数表示的是监视计算机上面的所有网卡的数据my_addr.sin_addr.s_addr = INADDR_ANY;//把一个名字绑定到我们的套接字上面bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));//3.listen():监听套接字的连接---------------------------------------------------------------------//sockfd表示需要监听的套接字描述符listen(sockfd, 10);addr_len = sizeof(struct sockaddr);while(1){printf("Server is waiting for client to connect:\n");//4.accept():等待客户端的请求----------------------------------------------------------------------------------//第二个参数:访问过来的客户端的地址//这个就是输出型参数(运行完之后客户端的地址就被放到这个位置,不需要我们手动填充)//accept返回值就是新的套接字描述符,新的客户端描述符,客户端有请求,就会返回新的套接字描述符client_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &addr_len);//inet_ntoa函数作用就是把我们的internet主机地址从二进制转换为点分的10进制,例如这个192.168.等等之类的printf("Client IP address = %s\n", inet_ntoa(client_addr.sin_addr));//5.send()服务器发送消息到客户端--------------------------------------------------------------------------------//第二个参数就是发送的内容char welcome[SIZE] = "Welcome to connect to the sever!";send(client_sockfd, welcome, SIZE, 0);printf("Disconnect the client request.\n");//6.close()---关闭客户端的连接---------------------------------------------------------------------------------close(client_sockfd);}close(sockfd);return 0;
}

5.TCP客户端编程

#define PORT_ID	8800
#define SIZE	100//./client IP  : ./client 192.168.0.10
int main(int argc, char *argv[])
{int sockfd;//这个结构体里面的是服务器端的这个地址struct sockaddr_in server_addr;char buf[SIZE];//当我们输入的参数后面没有这个IP地址的时候,我们需要给出这个提示信息,提示用户给出来IP地址//agrc表示的就是参数的个数if(argc < 2){printf("Usage: ./client [server IP address]\n");exit(1);}//1.socket()sockfd = socket(AF_INET, SOCK_STREAM, 0);//2.connect()server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT_ID);//argv[1]这个表示的就是命令行参数里面和IP地址相关的这个参数server_addr.sin_addr.s_addr = inet_addr(argv[1]);connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));//recv函数表示服务器端对于客户端发来的数据的接受,buf这个表示接受的信息内容放到buf里面去recv(sockfd, buf, SIZE, 0);printf("Client receive from server: %s\n", buf);close(sockfd);return 0;
}

6.UDP服务端编程

和上面的这个TCP想比较,这个UDP就简单了很多:

UDP没有accept函数获得客户端的信息,我们无法知道谁发送给我们的信息;

我们想要获得这个谁发送的,我们使用这个recvfrom知道谁发送到我们客户端的;

#define PORT_ID	8800
#define SIZE	100int main(void)
{int sockfd;struct sockaddr_in my_addr, client_addr;int addr_len;char buf[SIZE];//1.socket()sockfd = socket(AF_INET, SOCK_DGRAM, 0);//2.bind()my_addr.sin_family = AF_INET;my_addr.sin_port = htons(PORT_ID);my_addr.sin_addr.s_addr = INADDR_ANY;bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));addr_len = sizeof(struct sockaddr);while(1){printf("Server is waiting for client to connect:\n");//4.recvfrom()函数可以让我们知道这个接收到的数据的来源recvfrom(sockfd, buf, SIZE, 0, (struct sockaddr *)&client_addr, &addr_len);printf("Server receive from client: %s\n", buf);}close(sockfd);return 0;
}

7.UDP客户端编程

#define PORT_ID	8800
#define SIZE	100//./client IP  : ./client 192.168.0.10
int main(int argc, char *argv[])
{int sockfd;struct sockaddr_in server_addr;char buf[SIZE];int i;if(argc < 2){printf("Usage: ./client [server IP address]\n");exit(1);}//1.socket()sockfd = socket(AF_INET, SOCK_DGRAM, 0);server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT_ID);server_addr.sin_addr.s_addr = inet_addr(argv[1]);for(i = 0; i < 10; i++){sprintf(buf, "%d\n", i);sendto(sockfd, buf, SIZE, 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));printf("Client sends to server %s: %s\n", argv[1], buf);sleep(1);}close(sockfd);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/428200.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动化测试常用函数

目录 一、元素的定位 1、cssSelector 2、xpath &#xff08;1&#xff09;xpath 语法 1、获取HTML页面所有的节点 2、获取HTML页面指定的节点 3、获取一个节点中的直接子节点 4、获取一个节点的父节点 5、实现节点属性的匹配 6、使用指定索引的方式获取对应的节点内容…

鸿蒙OpenHarmony【轻量系统内核通信机制(消息队列)】子系统开发

消息队列 基本概念 消息队列又称队列&#xff0c;是一种任务间通信的机制。消息队列接收来自任务或中断的不固定长度消息&#xff0c;并根据不同的接口确定传递的消息是否存放在队列空间中。 任务能够从队列里面读取消息&#xff0c;当队列中的消息为空时&#xff0c;挂起读…

Linux--禁止root用户通过ssh直接登录

原文网址&#xff1a;Linux--禁止root用户通过ssh直接登录_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Linux服务器怎样禁止root用户通过ssh直接登录。 为什么要禁止&#xff1f; 因为root用户是每个Linux系统都有的&#xff0c;黑客可以使用root用户名尝试不同的密码来暴力破…

ClickHouse 与 Quickwit 集成实现高效查询

1. 概述 在当今大数据分析领域&#xff0c;ClickHouse 作为一款高性能的列式数据库&#xff0c;以其出色的查询速度和对大规模数据的处理能力&#xff0c;广泛应用于在线分析处理 (OLAP) 场景。ClickHouse 的列式存储和并行计算能力使得它在处理结构化数据查询时极具优势&…

【Elasticsearch】-spring boot 依赖包冲突问题

<dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.17.24</version></dependency> 在pom的配置中&#xff0c;只引入了elasticsearch-7.17.24 &#xff0c;但实际上会同时…

seq2seq翻译实战-Pytorch复现

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 code from __future__ import unicode_literals, print_function, division from io import open import unicodedata import string import re import rando…

半导体器件制造5G智能工厂数字孪生物联平台,推进制造业数字化转型

半导体器件制造行业作为高科技领域的核心驱动力&#xff0c;正积极探索和实践以5G智能工厂数字孪生平台为核心的新型制造模式。这一创新不仅极大地提升了生产效率与质量&#xff0c;更为制造业的未来发展绘制了一幅智能化、网络化的宏伟蓝图。 在半导体器件制造5G智能工厂中&a…

RabbitMQ 高级特性——发送方确认

文章目录 前言发送方确认confirm 确认模式return 退回模式 常见面试题 前言 前面我们学习了 RabbitMQ 中交换机、队列和消息的持久化&#xff0c;这样能够保证存储在 RabbitMQ Broker 中的交换机和队列中的消息实现持久化&#xff0c;就算 RabbitMQ 服务发生了重启或者是宕机&…

中间件知识点-消息中间件(Rabbitmq)一

消息中间件介绍 MQ的作用(优点)主要有以下三个方面&#xff1a; a.异步 b.解耦 c.削峰 MQ的作用(缺点)主要有以下三个方面&#xff1a; a.系统可用性降低 b.系统复杂度提高 c.存在消息一致性问题需要解决 备注&#xff1a; 引入MQ后系统的复杂度会大大提高。 以前服务之间可以…

【软件基础知识】什么是 API,详细解读

想象一下,你正在使用智能手机上的天气应用。你打开应用,瞬间就能看到实时天气、未来预报,甚至是空气质量指数。但你有没有想过,这些数据是如何神奇地出现在你的屏幕上的?答案就在三个字母中:API。 API,全称Application Programming Interface(应用程序编程接口),是现代软件世…

计算机网络 --- 初识协议

序言 上一篇文章中 &#xff08;&#x1f449;点击查看&#xff09;&#xff0c;我们简单的了解了怎么寻找目标计算机&#xff0c;需要通过交换机&#xff0c;路由器等设备跨越多个网络来不断的转发我们需要传输的数据&#xff0c;直至到达目标计算机。  那我们设备之间数据是…

重回极简:华为如何走向全面智能化?

“人类发现地球只是宇宙一员的时候&#xff0c;也是我们距离群星最遥远的时候。” 这个来自天文领域的喟叹&#xff0c;今天同样出现在行业与企业的智能化之路上。在这个时代坐标上&#xff0c;AI大模型技术极速成熟&#xff0c;AIGC和AI Agent等应用受到了各个行业的巨大期待。…

昇腾大模型推理解决方案MindIE部署

MindIE大模型推理套件 MindIE&#xff08;Mind Inference Engine&#xff0c;昇腾推理引擎&#xff09;是华为公司针对AI全场景推出的整体解决方案&#xff0c;包含丰富的推理加速套件。通过开放各层次AI能力&#xff0c;支撑客户多样化的AI业务需求&#xff0c;使能百模千态&a…

存储 NFS

目录 1.存储的应用场景 2.存储分类 3.NFS服务组成 4.环境说明 ​编辑 5.服务端部署 6.NFS服务端的配置 7.NFS服务端本地进行测试 1.存储的应用场景 存储一般用于上传网站数据&#xff08;内容&#xff09;&#xff0c;一般用于在网站集群中。使用存储的话用户上传的…

成型的程序

加一个提示信息 加上python 常用的包 整个程序打包完 250M 安装 960MB matplot numpy pandas scapy pysearial 常用的包 (pyvisa)… … 啥都有 Python 解释器组件构建 要比 lua 容易的多 &#xff08;C/Rust 的组件库)

JavaSE--集合总览02:单列集合Collection的体系之一:List

Collection体系的特点 分为 list 和set集合&#xff0c;这篇文章主要讲述List&#xff0c;下篇讲述Set。 简单认识单列集合collection集合的特点 : list集合的特点&#xff1a; 有序 可重复 有索引 set集合的特点&#xff1a;无序 不重复 无索引 其中LinkedHashSet有序 TreeS…

微服务架构陷阱与挑战

微服务架构6大陷阱 现在微服务的基础设施还是越来越完善了&#xff0c;现在基础设施缺乏的问题逐渐被解决了。 拆分粒度太细&#xff0c;服务关系复杂 拆分降低了服务的内部复杂度&#xff0c;但是提升了系统的外部复杂度&#xff0c;服务越多&#xff0c;服务和服务之间的连接…

from tqdm.auto import tqdm用法详细介绍

tqdm 是一个 Python 库&#xff0c;用于在长时间运行的任务中显示进度条。tqdm.auto 是 tqdm 的一个版本&#xff0c;能够自动适配输出环境&#xff08;如 Jupyter Notebook、命令行等&#xff09;&#xff0c;以确保进度条在各种环境下显示正确。下面是 tqdm.auto 的详细用法介…

每天五分钟计算机视觉:将人脸识别问题转换为二分类问题

本文重点 在前面的课程中,我们学习了两种人脸识别的网络模型,这两种人脸识别网络不能算是基于距离或者Triplet loss等等完成的神经网络参数的学习。我们比较熟悉的是分类任务,那么人脸识别是否可以转变为分类任务呢? 本节课程我们将介绍一种全新的方法来学习神经网络的参…

用友U8二次开发工具KK-FULL-*****-EFWeb使用方法

1、安装: 下一步&#xff0c;下一步即可。弹出黑框不要关闭&#xff0c;让其自动执行并关闭。 2、服务配置&#xff1a; 输入服务器IP地址&#xff0c;选择U8数据源&#xff0c;输入U8用户名及账号&#xff0c;U8登录日期勾选系统日期。测试参数有效性&#xff0c;提示测试通过…