Linux系统下利用共享内存模拟迅雷下载
我的思路比较简单,具体总结如下:
1、服务器端启动,直接将所有文件上传至共享内存区
2、在服务器端本次共模拟两个文件,视频文件 1.mp4、图片1.jpg,两个文件各开辟一块过程内存区
3、文件资源名字通过映射发送至两端
4、客户端启动,通过文件名字自主选择要下载的文件资源
5、主函数中由父进程创建两个兄弟进程,由父进程发送自定义信号,指挥其子进程进行下载
这里总结一下我遇到的比较大的问题:
1、如果上传文本文件,在客户端获取文件大小比较简单,strlen()函数直接搞定,因为文本文件中存储的其实可以看成一个比较的字符串而已。
但是音视频以及图片类型的二进制文件,strlen()函数则无法运用,我也尝试了不少方法,例如循序判断字符,lseek等等,都无济于事。所这里我再次开辟了一块共享内存区存储文件的大小。
2、如何通过父进程指挥其子进程去下载呢?
我是通过注册自定义信号SIGUSR1和SIGUSR2,然后通过kill(getpid(),执行函数)传递信号,去指挥子进程下载。
3、其他细微问题这里便不再赘述,都是一些变量未初始化、函数参数忘记使用、未删除映射区、未删除共享内存关联等等小问题。
废话不多说,上代码!
服务器端:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <error.h>
#include <string.h>
#include <time.h>
#include <signal.h>#define SHMKEY01 100//1.jpg的共享内存区
#define SHMKEY02 200//1.mp4的共享内存区
#define SHMKEY03 300//1.txt的共享内存区
#define SIZE 4096000int shmid,shmid02,shmid03;
char *buf = NULL;//共享内存1
char *buf02 = NULL;//共享内存2
int fp;//文件描述符1
int fp02;//文件描述符2
int fp03;//文件描述符3
int fd;//内存映射static int num01=0;
static int num02=0;typedef struct
{int n1;int n2;
}NUM;
NUM info[1];
NUM *buf03 = NULL;//共享内存3int main(int argc,char *argv[])
{printf("文件正在上传服务器,请稍后...\n");sleep(3);printf("文件上传成功!\n");shmid = shmget(SHMKEY01, SIZE, 0664 | IPC_CREAT);if(shmid==-1){printf("servre()...shmget() fail!\n");exit(1);}printf("server() shmid=%d\n",shmid);buf = (char *)shmat(shmid, NULL, 0);if(NULL == buf){perror("error");exit(1);}fp = open("/home/lianpan/0924/homework/1.jpg",O_RDONLY);//上传图片1.jpg int ret01 = read(fp,buf,SIZE);printf("当前服务器获取到文件1.jpg共%d个字节\n",ret01);info[0].n1 = ret01;shmid02 = shmget(SHMKEY02, SIZE, 0664 | IPC_CREAT);if(shmid02 == -1){printf("servre()...shmget() fail!\n");exit(1);}printf("server() shmid02=%d\n",shmid02);buf02 = (char *)shmat(shmid02, NULL, 0);if(NULL == buf02){perror("error");exit(1);}fp02 = open("/home/lianpan/0924/homework/1.mp4",O_RDONLY);//上传视频1.mp4int ret02 = read(fp02,buf02,SIZE);printf("当前服务器获取到文件1.mp4共%d个字节\n",ret02);info[0].n2 = ret02;shmid03 = shmget(SHMKEY03, 4, 0664 | IPC_CREAT);if(shmid03 == -1){printf("servre()...shmget() fail!\n");exit(1);}printf("server() shmid03=%d\n",shmid03);buf03 = (NUM *)shmat(shmid03, NULL, 0);if(NULL == buf03){perror("error");exit(1);}*buf03 = info[0];fd = open("readme.txt",O_RDWR|O_CREAT,0664);//readme.txt文件映射到共享内存区if(-1 == fd){perror("内存映射失败");exit(-1);}int len = lseek(fd,0,SEEK_END);printf("当前服务器获取到文件readme.txt为%d个字节大小\n",len);system("ipcs -m");
// printf("info[0].n1=%d,info[0].n2=%d\n",info[0].n1,info[0].n2);char *p = NULL;p = mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);//将文件映射到共享内存if(p == MAP_FAILED){perror("mmap error");exit(1);}
// printf("文件read.txt的内容为:\n%s\n",p);munmap(p,len);//关闭映射区close(fp);//关闭文件描述符close(fp02);shmdt(buf);shmdt(buf02);sleep(15);return 0;
}
客户端:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <error.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <pthread.h>#define SHMKEY01 100//1.jpg的共享内存区
#define SHMKEY02 200//1.mp4的共享内存区
#define SHMKEY03 300//1.txt的共享内存区
#define SIZE 4096000int shmid,shmid02,shmid03;//共享内存返回值
int pid;//父子进程
char *buf = NULL;//共享内存1
char *buf02 = NULL;//共享内存2
//char *buf03 = NULL;//共享内存3
int fp;//文件描述符1
int fp02;//文件描述符2
int fp03;//文件描述符3
int fd;//内存映射
int len;//映射区内容大小
int num1 = 0;//接收文件大小
int num2 = 0;//接收文件大小typedef struct
{int n1;int n2;
}NUM;
NUM *buf03 = NULL;void client01()
{shmid = shmget(SHMKEY01, SIZE, 0);if(shmid==-1){printf("servre()...shmget() fail!\n");exit(1);}printf("server() shmid=%d\n",shmid);buf = (char *)shmat(shmid, NULL, 0);if(NULL == buf){perror("error");exit(1);}/*int mm=0;for(int j=0;;j++){if(*(buf+j) == EOF)break;else mm++;}printf("mm=%d\n",mm);int mmm = strlen(buf);printf("mmm=%d\n",mmm);*/fp = open("1.jpg",O_RDWR|O_CREAT,0777);int ret = write(fp,buf,num1);int n = lseek(fp,0,SEEK_END);printf("文件1.jpg的大小为:%d\n",n);if(ret == -1){perror("write error");exit(1);}elseprintf("由共享内存区buf写入到文件1.jpg大小为:%d\n",n);close(fp);//此时就可以关闭文件描述符
}void client02()
{shmid02 = shmget(SHMKEY02, SIZE, 0);if(shmid02 == -1){printf("servre()...shmget() fail!\n");exit(1);}printf("server() shmid02=%d\n",shmid02);buf02 = (char *)shmat(shmid02, NULL, 0);if(NULL == buf02){perror("error");exit(1);}fp02 = open("1.mp4",O_RDWR|O_CREAT,0777); int ret = write(fp02,buf02,num2);int m = lseek(fp02,0,SEEK_END);printf("文件1.mp4的大小为:%d\n",m);if(ret == -1){perror("write error");exit(1);}elseprintf("由共享内存区buf02写入到文件2.txt大小为:%d\n",ret);close(fp02);
}void client03()
{shmid03 = shmget(SHMKEY03, 4, 0664 | IPC_CREAT);if(shmid03 == -1){printf("servre()...shmget() fail!\n");exit(1);}printf("server() shmid03=%d\n",shmid03);buf03 = (NUM *)shmat(shmid03, NULL, 0);if(NULL == buf03){perror("error");exit(1);}
// printf("%d\n",buf03->n1);
// printf("%d\n",buf03->n2); }//内存映射
void mmaptest(void)
{fd = open("../readme.txt",O_RDWR|O_CREAT,0664);//readme.txt文件映射到共享内存区if(-1 == fd){perror("内存映射失败");exit(-1);}int len = lseek(fd,0,SEEK_END);
// printf("当前获取到文件readme.txt为%d个字节大小\n",len);char *p = NULL;p = mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);//将文件映射到共享内存if(p == MAP_FAILED){perror("mmap error");exit(1);}
// printf("文件readme.txt的内容为:\n%s\n",p);
}int main(int argc,char *argv[])
{client03();//内存共享获取文件大小num1 = buf03->n1;//结构体元素赋值全局变量num2 = buf03->n2;
// printf("%d\n",num1);
// printf("%d\n",num2); char ch;int SHMKEY04 = 400;shmid03 = shmget(SHMKEY04,4,IPC_CREAT | 0777);if(shmid03 == -1){printf("main...shmget() fail!\n");exit(1);}printf("创建共享内存成功 shmid03=%d\n",shmid03);int *p = NULL;int j=0;p = (int *)shmat(shmid03,NULL,0);*p = 1;signal(SIGUSR1,client01);//注册自定义信号1signal(SIGUSR2,client02);//注册自定义信号2
// signal(SIGUSR3,client02);mmaptest();printf("请选择您要下载的文件资源:\n1、1.jpg\n2、1.mp4\n");scanf("%c",&ch);switch(ch){case '1':pid = fork();if(pid == 0){printf("我是第一个子进程\n");if(*p == 1){printf("文件正在下载中,请等待...\n");static int n=6;for(int j=0;j<5;j++){printf("目前下载进程...%d%%\n",n);n += 13;usleep(500000);}printf("目前下载进程...100%%\n");printf("文件下载成功,请返回查看!\n");kill(getpid(),SIGUSR1);*p = 0;sleep(1);}}else if(pid > 0){// printf("我是父进程\n");}break;case '2':pid = fork();if(pid == 0){printf("我是第二个子进程\n");static int n=7;if(*p == 1){printf("文件正在下载中,请等待...\n");for(int j=0;j<5;j++){printf("目前下载进程...%d%%\n",n);n += 13;usleep(500000);}printf("目前下载进程...100%%\n");printf("文件下载成功,请返回查看!\n");kill(getpid(),SIGUSR2);*p = 0;sleep(1);}}else if(pid > 0){// printf("我是父进程\n");}break;default:break;}shmctl(shmid,IPC_RMID,0);//删除共享内存区shmctl(shmid02,IPC_RMID,0);shmctl(shmid03,IPC_RMID,0);munmap(p,len);//删除映射区return 0;
}
运行结果:
Linux系统下利用共享内存模拟迅雷下载相关推荐
- linux系统安装内存测试,一种Linux系统下基于IDK内存注错的测试方法及系统与流程...
本发明涉及计算机服务器的 技术领域: :,具体涉及到一种Linux系统下基于IDK内存注错的测试方法及系统. 背景技术: ::在服务器领域中,内存是服务器中重要的部件之一,它是与CPU进行沟通的桥梁. ...
- Unix/Linux操作系统分析实验二 内存分配与回收:Linux系统下利用链表实现动态内存分配
Unix/Linux操作系统分析实验一 进程控制与进程互斥 Unix/Linux操作系统分析实验三 文件操作算法: 实现在/proc目录下添加文件 Unix/Linux操作系统分析实验四 设备驱动: ...
- java 内存映射文件进程间通讯_[转]Windows环境下利用“共享内存”实现进程间通信的C/C++代码---利用CreateFileMapping和MapViewOfFile...
进程间的通信方式有很多种, 上次我们说了最傻瓜的"共享外存/文件"的方法. 那么, 在本文中, 我们即将学习"共享内存"的方式实现进程间的通信, 这是IPC最快 ...
- linux系统下文件的上传和下载(rz、sz)
linux系统下的rz.sz上传和下载 rz 是从本地上传文件的时候用的, sz 相当于把Linux 服务器上的文件 下载到 本地. 通过这两个命令就可以把 Windows 和Linux 的文件 进行 ...
- Linux系统编程—进程间通信—共享内存
Linux共享内存 共享内存就是允许两个或多个进程共享一定的存储区.就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时候,其它进程都会察觉 ...
- Linux系统下利用Impost3r劫持sudo命令窃取凭据
Impost3r是一款针对Linux平台的密码窃取工具,该工具采可以在linux系统的普通用户权限下制造水坑,从目标Linux主机中获取各类密码如ssh.su.sudo等. 软件使用 C 语言编写,可 ...
- opencv在linux系统下利用从cv2进行摄像头读取操作
读取一直错误 根本没显示 ,后来查阅了好久发现是ubuntu中的摄像头褐诶主机的摄像头不匹配的问题, 来到主机,将主机中相机权限打开,进行共享,再回到ubuntu进行cheese命令检验,终于实现视 ...
- Unix/Linux操作系统分析实验四 设备驱动: Linux系统下的字符设备驱动程序编程
Unix/Linux操作系统分析实验一 进程控制与进程互斥 Unix/Linux操作系统分析实验二 内存分配与回收:Linux系统下利用链表实现动态内存分配 Unix/Linux操作系统分析实验三 文 ...
- linux中split分割文件打开方式,Linux系统下使用split命令分割大文件 (转载)
[小蜗牛闲情之作 ] 我想给一个朋友传一个大视频,有几百M,尝试多种传输办法失败后,最后想到的是把视频切开一片片"邮递"过去给他,让它自己组装起来吧. [root@pps publ ...
- linux第三方模块参数,nginx 的第三方模块ngx_http_accesskey_module 来实现下载文件的防盗链步骤(linux系统下)...
nginx 的第三方模块ngx_http_accesskey_module 来实现下载文件的防盗链步骤(linux系统下),安装Nginx和HttpAccessKeyModule模块(参考LNMP环境 ...
最新文章
- 客户端爬取-答网友问
- JAVA_OPTS 参数
- Secure保存串口数据到本地
- 文巾解题 196. 删除重复的电子邮箱
- 中科院计算机全国重点实验室,国家重点实验室
- Mozilla “Common Voice” 开源语音识别项目
- 如何杀掉D状态的进程?[zt]【转】
- java ajax报错500,(Struts2+JSON+Ajax) XMLHttpRequest ==500如何解决
- linux ssh客户端_Linux终端连接Linux服务器
- ASP.NET把图片存入数据库和使用文件流读取显示(转)
- python实现json文件中向量写入Excel中
- 组策略设置计算机计划任务,组策略 运行计划任务 Powershell
- 软考高级信息系统项目管理师经验分享
- ctf比赛/学习资源整理,记得收藏!
- 关闭删库跑路的后门,打造高可用的MySQL
- random.uniform()和random.random()区别
- 【STL】string详解(string类常用的操作函数、构造函数、赋值操作、子符串的拼接、查找和替换、比较、存取、插入和删除、获取)
- 打卡系列-剑指 Offer 62. 圆圈中最后剩下的数字
- 毕业三年,快速升职加薪,带领数十人的技术团队,我是怎么做到的?
- 虚函数和纯虚函数的使用
热门文章
- php 上传微信客服头像,微信多客服上传头像
- 计算机专业就业崩溃,计算机专业就业“遇冷说”引发争议
- Java继承的特征和优势
- Python学习教程-1_Introductions
- 视差贴图(Parallax Mapping)
- 武汉理工大学计算机学院导师联系方式,武汉理工大学计算机学院导师一览表
- 短视频合集怎么做,教你快速合并的技巧
- ibm服务器维修检测报告,启创云小机(IBM POWER7)测试报告
- CorelDRAW VBA - 发布(导出)PDF文档
- 举个栗子~Minitab 技巧(6):使用 T 检验 分析产品质量