应用开发
2023-01-07 10:54:45 0 举报
AI智能生成
登录查看完整内容
c语言线程,进程,网络通信总结
作者其他创作
大纲/内容
应用开发
普通,目录,管道,链接,套接字,块,字符设备文件
7种文件类型
打开文件 6种方式font color=\"#ffb74d\
读写文件 fread fwrite
关闭文件fclose
FILE * fp 文件流指针
IO 函数操作,不能操作内核,设备
文件描述符 大于0的正整数
操作对象
① pathname -- 文件名,目录名 -- F_OK(存在与否)
② mode --- F_OK W_OK X_OK R_OK
int access(const char*pathnamefont color=\"#ffb74d\
access
权限 八进制数表示 0644 0755
mode
int open(const char*pathnamefont color=\"#ffb74d\
O_RDWR 可读可写
O_RDONLY 只读
O_WRONLY 只写
O_APPEND 追加
O_CREAT 创建
flags 打开方式
open
① fd -- open的返回值
② buf -- 缓冲区大小
③ count -- 读取的字节数
④ 返回值:读取的个数
ssize_t read(int fdfont color=\"#ffb74d\
read
ssize_t write(int fdfont color=\"#ffb74d\
write
① offset -- 相对于whence的偏移量(+,-,0)
② whence --- SEEK_SET 开头 SEEK_CUR 当前 SEEK_END 末尾
③ 返回值:当前位置距离开头的偏移量
off_t lseek(int fdfont color=\"#ffb74d\
lseek (重新设置读写的位置)
① path -- 文件名,路径名
② buf -- 存放,结构体内容
③ 返回值 -- 0 -- success -1 -- erro
int stat(const char *pathfont color=\"#ffb74d\
stat (文件的状态信息)
函数
IO文件操作
① mode -- 权限
② 返回值: 0 -- success -1-- error
int mkdir(const char*pathnamefont color=\"#ffb74d\
mkdir (创建目录)
rmdir(const char*pathname)
rmdir
pathname -- 目录流
dir --- 目录流指针(存放目录的信息)
DIR*dir = opendir(const char*pathname)
opendir (打开目录)
dir --- 目录流指针
d_name 文件名字
子主题
sp --- 指向dir目录的结构体指针
struct dirent *sp = readdir(DIR*dir)
readdir (读取目录中的文件信息)
rename(const char *oldnamefont color=\"#ffb74d\
rename (修改名字)
int remove(const char*pathname)
remove(删除文件,或者空的目录)
目录操作
文件管理
头文件
新建 就绪 运行 阻塞 结束 (三个回路)
进程的状态
ps aux--- linux中的进程
动态性 --- pid不连续,动态产生,动态消亡
并发性 --- 同时执行 -- 宏观
异步性 --- 不同时执行 -- 微观角度,时间差
独立性 --- 父子进程运行在不同的空间中
结构特性 --- 空间不同,所以具有不同的空间体系(栈,堆,数据,代码)
进程的特性
1、独立可调度的活动
2、抽象的实体,申请和释放资源
3、并行执行,多进程提供基础
4、进程是程序的一次执行过程,动态的,程序执行和资源管理的最小单元。进程的标识符
进程的概念
父进程 -- 创建子进行fork() -- 函数
pid_t pid = 0;
pid = fork(); if(pid == -1) { perror(\"fork\"); exit(1); }
pid = fork();
else if(pid == 0) { //子进程 printf(\"the child process![%d-%d]\\
else { //父进程 printf(\"the parent process![%d-%d]\\
getpid() --- 返回当前进程的pid
getppid() -- 子进程中返回父进程的编号
process(进程,动态的过程)
<stdio.h> <sys/ipc.h> <sys/shm.h> <stdlib.h> <sys/types.h>
int pipe(int pfd[2]);
pfd[2] -- 接收管道的描述符
返回值:0 -- success -1 --- error
pipe --- 创建无名管道
pathname -- 文件名,路径名
mode -- 权限
返回值:0--- success -1 --- error
mkfifo() --- 创建有名管道
查看共享内存:ipcs -m
1、创建共享内存
2、映射共享内存
3、span style=\"font-family:宋体;mso-ascii-font-family:Calibri;mso-ascii-theme-font:minor-latin;mso-fareast-theme-font:minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin\"使用共享内存
4、断开共享内存
5、回收共享内存
编程步骤:
pathname -- 存在
返回值:键值
key -->ftok() -- 返回值获得
size --->共享内存大小
shmflg --> IPC_CREAT|权限
返回值:shmid --- >共享内存的标识符
创建共享内存
进程间通信
任务(进程)
① 线程是进程的一个实体,轻量级进程
② 程序执行流的最小单元
③ 被系统独立调度和分派基本单元
(1) 什么是线程
① 进程和线程的概念
② 如果只有一个进程,那么这个进程既是进程也叫做线程
(2) 线程和进程关系
(3) 线程A --创建--- 线程B (线程B只拥有自己需要一点儿栈段空间,其他的共享资源)
(4) 运行图
线程
概念
#include <stdio.h>#include <pthread.h>#include <stdlib.h>#include <unistd.h>#include <string.h>
1、pthread_t*thread --- 新线程的编号
2、attr -- 线程的属性 NULL(默认属性)
3、void *(*start_routine) (void *) --》start_routine 指向返回值和参数都是void*的函数,---》新的线程
4、void*arg -- 作为新的线程的参数
5、返回值:success -- 0 error --- 错误编码 strerror打印
pthread_self() -- 返回线程的编号
pthread_exit(void*arg) -- 线程的结束函数(进程结束exit())
线程的创建
互斥问题 -- 只允许一个线程访问
同步问题 -- 在互斥保护下对于线程的有序访问
共享资源的访问 --- 全局变量(两个进程都可以访问到)
通过加锁和解锁的方式实现线程的通信,解决了线程的互斥的问题
(1) 静态初始化 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 快速互斥锁
1、申请互斥锁
pthread_mutex_lock(&mutex);
2、上锁
pthread_mutex_unlock(&mutex);
3、解锁
pthread_mutex_destroy(&mutex);
4、回收资源
互斥锁:锁的机制,上锁和解锁。
在互斥锁的保护下读文件 -- 线程 写文件 -- 线程执行 条件为真阻塞 -- 不执行了-- 释放锁改变条件-阻塞线程发送唤醒信号 接受到对方信号--不阻塞执行执行完成,改变条件让自己继续阻塞
总结:读线程先执行 -- 写的线程在执行(重复上一次过程)
(1) 静态初始化 -- pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
1、初始化
2、阻塞线程(条件为真)
pthread_cond_signal(&cond); -- 唤醒线程执行
3、唤醒一个阻塞的线程
pthread_cond_destroy(&cond) -- 回收条件变量
前提,2个线程必须在互斥锁的保护下进行
条件变量的操作流程
条件变量:条件,变量的改变 -- 线程的执行
AF_INET IPV4的协议族
SOCK_DGRAM(数据报套接字)
protocol:指定应用程序使用的通讯协议,一般取值为0,让系统决定使用协议
成功:返回新建的套接字描述符。失败返回-1,并将错误代码放入erron
创建socket通信
seraddr.sin_family = AF_INET;(协议)
seraddr.sin_port = htons(atoi(端口号));
seraddr.sin_addr.s_addr = inet_addr(IP地址);
socklen_t len = sizeof(seraddr);
struct sockaddr_in seraddr = {0}
设置ip和port
str:发送的字符串
seraddr:服务器地址
len:seraddr长度
发送消息
rv:接收消息的长度
接收消息
close(sockfd);
关闭套接字
客户端
struct sockaddr_in seraddr={0};
绑定IP和port
struct sockaddr_in cliaddr;
服务器
UDP编程
AF_INET ipv4的协议族
流式套接字(SOCK_STREAM)
成功:返回新建的套接字描述符;失败:返回-1。并将错误码放入 errno
返回值:0--success 1--error
连接服务器
也可以用write发送消息格式同read
-1失败
recv接收消息,格式同send
sockfd:监听客户端连接请求
20:l连接队列中的最大个数,自定
监听
socklen_t len=sizeof(cliaddr);
接收请求
TCP编程
int type
int id
head结构体
body结构体
char *comm = (char*)malloc(sizeof(struct head)+sizeof(struct body));
申请空间
head存入
body存入
组报
free
释放空间
HEAD*head = NULL;head = (HEAD*)comm;
BODY*body = NULL;body = (BODY*)(comm+sizeof(HEAD)
解析消息内容
服务端
通信协议设计
fd_set readfd;
申请文件描述符集合
FD_ZERO(&readfd);
分支主清空文件描述符的集合题
fd最大5
文件描述符顺次添加到文件描述符的集合中
struct timeval tm;int retval = 0;
设置等待时间
-1:error
0:无输入
返回值
阻塞的方式等待tm时长
maxfd最大值
内核监控(select)readfd中文件描述符的变化
否则循环判断fd变化
判断FD_ISSET()判断readfd中文件描述符状态是否可读,如果可读--通信,如果对方断开,把文件描述符从文件描述符集合中清除(FD_CLR())
最大连接个数的限制 1024
效率问题低,主要对于集合操作,线性扫面(所有集合中数据查看)
内存拷贝问题,select机制,把所有的文件描述符的集合方法内核中。
函数少,编码简单,能够实现IO的多路复用。
优缺点
select函数(非阻塞链接)
EPOLL_CTL_ADD 添加fd到节点上
EPOLL_CTL_MOD 修改fd在节点上
EPOLL_CTL_DEL 从节点删除fd
int epollfd = epoll_create(EPOLL_FLAG);
创建epoll节点
struct epoll_event ev;
可读EPOLLIN 可写EPOLLOUT 异常EPOLLERR
添加可读的事件
ev.events = EPOLLIN;
文件描述符
ev.data.fd = sockfd;
创建节点的结构体并赋值
0:success
-1:error
文件描述符 -- 添加到epoll的节点
EPOLL_FLAG值自定义
struct epoll_event even[EPOLL_FLAG];
创建监控事件的结构体数组
even:存储事件
EPOLL_FLAG:检测个数
时间 0 --- 立即返回 , -1-- 阻塞等待事件到来
活跃的文件描述符的个数max_fd
epoll内核监控这些节点
int ifd = even[i].data.fd;
accfd添加到epollfd
if((ifd == sockfd)&&(even[i].events == EPOLLIN))
0:断开连接
成功
else
轮询查看文件描述符变化
没有最大并发量的限制,打开文件的个数(6位数)
效率问题:只管活跃的文件描述符
内存拷贝问题:epoll机制,会和内存实现“内存共享”方式,减少拷贝,提高效率
相对于select的改进
epoll函数(非阻塞链接)
网络 (网络应用)
0 条评论
回复 删除
下一页