IO进程与线程

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;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值