2022.6.27
今天主要是学习了文件的IO,即读写操作,
函数的三要素,
1.函数返回类型
2.形参类型
3.函数返回值类型,
2022.6.28
今天已经学习完成了标准IO,继续学习还差文件IO;
标准IO,
1.来自C语言的库函数,
2.高级IO(何为高级,带缓存的IO)
liiuxI文件IO
1.来自系统调用库
2.低级IO,不带缓存
2022.6.30突如其来的头疼
今朝剑指叠运出,炼人炼蛊还炼天;
今天我们学习了库的创建
库又分为动态库与静态库
一级几个人函数的运用;
2022 .7.1
旧时王谢堂前燕,飞入寻常百姓家。
时间很快,
今天我们学了开启进程和线程。
2022.7.2 挟飞仙以遨游,抱明月而长终
共享文件果然祸福相依,在shell脚本学习时候不用chomd修改权限,但是在共享文件夹下,mkfifo,让我也许难受,不能正常执行;
进程间通信
2022.74
每个人都是自己观念的囚徒
信号灯集,消息队列,有名管道(无亲缘)无名管道(亲缘)共享内存;
无名管道(亲缘)
1.是"半双工"工作方式 "半双工"同时只能从一端写入,另一端读取.
2、无名管道不属于文件系统. 数据交互在"内核内存"完成.
3、无名管道只能用于亲缘进程间的通信.
函数接口:
pipe { int pipe(int pipefd[2]);
用法: int fd[2]; pipe(fd); fd[0] 表示读端 fd[1] 表示写端 }
ret = read()在读取管道时(与读取文件返回0有区别). 如果写端关闭 且当中没有内容可读则会返回0. ret == 0 如果写端没有关闭 且当中没有内容可读,read会阻塞
思考: 读端如果关闭,写端会出现什么状况
{ 读端如果关闭,写端的存在是没有意义的,所以内核会发送一个管道破裂信号(SIGPIPE),该信号会 默认结束 进程 }
写端如果关闭,读端会出现什么状况 { 当写端关闭,如果管道中还有内容则读端会继续读取,直到读取完成返回0. }
/*===============================================================
* Copyright (C) 2022 All rights reserved.
*
* 文件名称:w-pipe.c
*
* 创建日期:2022年07月01日
* 描 述:
*
* 更新日志:
*
================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd[2] = {0};
if(-1 == pipe(fd))
{
perror("pipe");
exit(-1);
}
pid_t pid;
if((pid = fork()) == -1)
{
perror("fork");
exit(-1);
}
else if(pid == 0)
{
close(fd[1]);
char buf[32] = {0};
int ret = 0;
while(1)
{
if((ret = read(fd[0], buf, sizeof(buf))) <= 0)
{
if(ret == 0)
{
printf("pipe is empty\n");
break;
}
else
{
perror("read");
exit(-1);
}
}
printf("recv:%s\n", buf);
}
exit(0);
}
else
{
close(fd[0]);
char buf[32] = {0};
int ret = 0;
int n = 10;
while(n--)
{
if(-1 == write(fd[1], "hello", 5))
{
perror("write");
exit(-1);
}
if(n == 5)
{
close(fd[1]);
}
sleep(1);
}
wait(NULL);
exit(0);
}
return 0;
}
有名管道
1、是"半双工"工作方式 "半双工"同时只能从一端写入,另一端读取.
2、有名管道属于文件系统. 数据交互在"内核内存"完成.
3、有名管道可以用于非亲缘进程间的通信. 指令mkfifo 可以直接创建管道文件. 接口函数: mkfifo() { 创建管道文件. int mkfifo(const char *pathname, mode_t mode);
/*===============================================================
* Copyright (C) 2022 All rights reserved.
*
* 文件名称:fifo_read.c
* 创建日期:2022年07月01日
* 描 述:
*
* 更新日志:
*
================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
if(mkfifo(argv[1], 0664) == -1)
{
perror("mkfifo");
return -1;
}
int r_fd = open(argv[1], O_RDONLY);
if(r_fd == -1)
{
perror("open");
return -1;
}
printf("fifo read success\n");
char buf[32] = {0};
while(1)
{
int ret = read(r_fd, buf, sizeof(buf));
if(ret <= 0)
{
if(ret == 0)
{
printf("fifo is empty\n");
break;
}
else
{
perror("read");
return -1;
}
}
printf("recv:%s\n", buf);
memset(buf, 0, sizeof(buf));
}
return 0;
}
/*===============================================================
* Copyright (C) 2022 All rights reserved.
*
* 文件名称:fifo_read.c
* 创建日期:2022年07月01日
* 描 述:
*
* 更新日志:
*
================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int w_fd = open(argv[1], O_WRONLY);
if(w_fd == -1)
{
perror("open myfifo");
return -1;
}
printf("fifo write success\n");
char buf[32] = {0};
while(1)
{
printf("input:");
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf)-1] = '\0';
if(write(w_fd, buf, strlen(buf)) == -1)
{
perror("write");
return -1;
}
memset(buf, 0, sizeof(buf));
}
return 0;
}
内存共享
概念:内核会寻找一片内存空间,然后将空间进行映射操作,能够把内存映射到用户空间。大大提 升了通信效率.
操作流程:
1. 创建共享内存空间 (内核里)
2. 映射内核空间 到 用户空间
3. 读/写该共享内存
4. 取消映射、删除共享内存 相关指令: ipcs -m :查看共享内存 ipcrm -m id: 删除共享内存 例如: ipcrm -m 1234
key_t ftok(const char *pathname, int proj_id);
{
获取key值:标识共享内存,以及用于区分共享内存用于亲缘 还是 可以用于非亲缘.
key_t ftok(const char *pathname, int proj_id)
pathname: 文件名
proj_id: 组合成key 需要用到的id 返回值:错误返回-1 正确返回 获取到的key值. key 值是通过两个参数(文件的节点号 与 proj_id的值)组合形成的
}
int shmget(key_t key, size_t size, int shmflg); { 创建共享内存. key: IPC_PRIVATE 或 ftok的返回值 IPC_PRIVATE只能用于亲缘进程 size: 共享内存区大小 shmflg: 相当于open函数的权限位,也可以用8进制表示法 shmflg如包含IPC_CREAT,表明如果指定的共享内存不存在,则新建一个对象 返回值: 正确返回 共享内存段标识符(共享内存id) 错误 -1 }
void *shmat(int shmid, const void *shmaddr, int shmflg);
{ 共享内存映射. shmid:要映射的共享内存区标识符
shmaddr: 将共享内存映射到指定地址(若为NULL,则表示由系统自动完成映射)
shmflg: SHM_RDONLY:共享内存只读 默认0:共享内存可读 成功:映射后的地址 错误 -1
}
读/写 就是对内存的读写 比如fgets(),printf()... int shmdt(const void *shmaddr);
{ 取消映射 shmaddr: 共享内存映射后的地址 成功 0 错误 -1 }
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
{
共享内存控制函数.
shmid:要操作的共享内存标识符
cmd : IPC_STAT (获取对象属性) IPC_SET (设置对象属性) IPC_RMID (删除对象) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 信号灯集 消息队列
buf : 指定IPC_STAT/IPC_SET时用以保存/设置属性 当参数二为 IPC_RMID时 为 NULL
成功 0 错误 -1
}
信号灯集,消息队列。
//信号灯集进行P+,V-操作,实现阻塞同步;
/*************************************************************************
> File Name: 1_semaphore.c
> Author: 枫叶
> Mail: 719993600@qqcom
> Created Time: 2022年07月04日 星期一 08时59分14秒
***********************************************************************/
#include<stdio.h>
/************************************************************************
* 文件说明
************************************************************************/
#include <sys/types.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/sem.h>
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
};
int main(int argc, char *argv[])
{
//1、创建信号灯集
int semid = semget(IPC_PRIVATE, 2, IPC_CREAT | 0644);
if (semid < 0){
perror("semget");
return -1;
}
system("ipcs -s");
//2、初始化信号灯
union semun value1 = {0}; //初值为 0
semctl(semid, 0, SETVAL, value1); //设置编号为 0的信号灯初值为 0
union semun value2 = {1};
semctl(semid, 1, SETVAL, value2); //设置编号为 1的信号灯初值为 1
int shmid = shmget(IPC_PRIVATE, 32, IPC_CREAT | 0644);
if (shmid < 0){
perror("shmget");
return -1;
}
system("ipcs -m");
char *p = shmat(shmid, NULL, 0);
if ( p == (char *)-1){
perror("shmat");
return -1;
}
pid_t pid = fork();
if (pid < 0){
perror("fork");
return -1;
}else if(pid == 0){
while(1){
struct sembuf buf1 = {
.sem_num = 1, //待操作的信号灯编号
.sem_op = -1, //p操作
.sem_flg = 0 //阻塞等待
};
semop(semid, &buf1, 1); //p(1)
fgets(p, 32, stdin);
struct sembuf buf2 = {
.sem_num = 0, //待操作的信号灯编号
.sem_op = 1, //v操作
.sem_flg = 0 //阻塞等待
};
semop(semid, &buf2, 1); //V(0)
//if( strncmp(p, "quit", 4) == 0){ //strstr :字符串中查找子串
if(strstr(p, "quit") != NULL){
break;
}
}
} else{
waitpid(pid, NULL, WNOHANG);
while(1){
struct sembuf buf1 = {0, -1, 0};
semop(semid, &buf1, 1); //p(0)
printf("recv: %s\n", p);
struct sembuf buf2 = {1, 1, 0};
semop(semid, &buf2, 1); //V(1)
if(strncmp(p, "quit", 4) == 0){
break;
}
}
if(shmdt(p) < 0){
perror("shmdt");
return -1;
}
char buf[32] = {0};
sprintf(buf, "ipcrm -m %d -s %d", shmid, semid);
system(buf);
system("ipcs -m -s");
}
return 0;
}
/*******************************end of file*****************************/
消息队列代码
/*===============================================
* 文件名称:2.c
* 创 建 者:
* 创建日期:2022年07月04日
* 描 述:
================================================*/
#include <stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#include<stdlib.h>
#include <sys/ipc.h>
#include <sys/wait.h>
struct msgbuf{
long type;
char buf[32];
int data;
};
int main(int argc, char *argv[])
{
//创建消息队列
int msqid = msgget(IPC_PRIVATE,IPC_CREAT | 0644);
if(msqid<0)
{
perror("msgget");
return -1;
}
system("ipcs -q");
int pid=fork();
if(pid<0)
{
perror("fork");
return -1;
}
else if(pid == 0)
{
while(1)
{
struct msgbuf msg;
msg.type=10;
msg.data=1024;
fgets(msg.buf,32,stdin);
int ret=msgsnd(msqid,&msg,sizeof(msg)-sizeof(long),0);
if(ret==-1)
{
perror("msqsnd");
return -1;
}
if(strncmp(msg.buf,"qiut",4)==0)
break;
}
}
else
{
waitpid(pid,NULL,WNOHANG);
while(1)
{
struct msgbuf msg={0};
int ret1=msgrcv(msqid,&msg,sizeof(msg)-sizeof(long),10,0);
if(ret1==-1)
{
perror("msgrvc");
return -1;
}
printf("ret1=%d\n",ret1);
printf("data:%d\n",msg.data);
printf("buf:%s\n",msg.buf);
if(strncmp(msg.buf,"qiut",4)==0)
break;
}
if(msgctl(msqid,IPC_RMID,NULL)<0)
perror("msgctl");
}
system("ipcs -q");
return 0;
}