IO进程线程day8

目录

1.使用三个进程来完成输出 ABCABCABCABCABC

2. 将共享内存和信号灯集完成两个进程间通信程序重新实现一下

思维导图:

左值和右值:

如果两个指针同时指向一片地址,如果一个指针释放掉,另一个指针怎么知道已经释放了?


1.使用三个进程来完成输出 ABCABCABCABCABC

test1.c

#include <head.h>
#include "sem.h"
int main(int argc, const char *argv[])
{
	//创建一个信号灯集
	int semid = create_sem(3);
	if(semid ==-1){
		perror("create_sem error");
		return -1;
	}

	//定义两个进程号
	pid_t pid1 =-1;
	pid_t pid2 =-1;
	int n=5;

	//创建进程
	pid1=fork();
	if(pid1>0){
		pid2=fork();
		if(pid2>0){
			//父进程
			while(n--){
				P(semid,2); //申请信号灯2资源
				printf("A");
				fflush(stdout);
				V(semid,0); //释放信号灯0资源
			}

			wait(NULL); //回收子进程资源
			wait(NULL); //回收子进程资源
		}else if(pid2==0){
			//子进程2
			while(n--){
				P(semid,0); //申请信号灯0资源
				printf("B");
				fflush(stdout);
				V(semid,1); //释放信号灯1资源
			}
			exit(EXIT_SUCCESS); //退出子进程2

		}else{
			perror("fork2 error");
			return -1;
		}
	}else if(pid1==0){
		//子进程1
		while(n--){
			P(semid,1); //申请信号灯1资源
			printf("C");
			fflush(stdout);
			V(semid,2); //释放信号灯2资源
		}
		exit(EXIT_SUCCESS); //退出子进程1
	}else{
		perror("fork1 error");
		return -1;
	}

	puts("");
	//删除信号灯集
	del_sem(semid);
	return 0;
} 

sem.h

#ifndef __SEM_H__
#define __SEM_H__

//信号灯集的申请,初始化信号灯,并返回信号灯集的id
int create_sem(int semcount);

//申请信号灯资源操作  P操作
int P(int semid,int semno);

//释放信号灯资源操作  V操作
int V(int semid,int semno);

//信号灯集的删除
int del_sem(int semid);

#endif

sem.c

#include <head.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 init_sem(int semid, int semno)
{
    int val = -1;
    printf("请输入标号为%d的灯的初始值:", semno);
    scanf("%d", &val);
	getchar();

    //对当前灯进行赋初始值
    //定义一个共用体变量
    union semun us;
    us.val = val;            //要赋的值
    if(semctl(semid, semno, SETVAL, us) == -1)
    {
        perror("set val error");
        return -1;
    }

    //成功返回0
    return 0;
}

//信号灯集的申请,初始化信号灯,并返回信号灯集的id
int create_sem(int semcount){
	//1.创建key值
	key_t key = ftok("/",'y');
	if(key==-1){
		perror("ftok error");
		return -1;
	}

	//2.通过key值创建一个信号灯集
	int semid =semget(key,semcount,IPC_CREAT|IPC_EXCL|0664);
	if(semid==-1){
		if(errno==EEXIST){
			//说明信号灯集已经存在,无需创建直接打开即可
			semid = semget(key,semcount,IPC_CREAT);
			return semid;
		}
		perror("semget error");
		return -1;
	}
	//3、给信号灯集中的信号灯进行初始化操作
    for(int i=0; i<semcount; i++)
    {
        init_sem(semid, i);            //初始化标号为i的灯value值
    }

    //4、返回值信号灯集的id
    return semid;
}

//申请信号灯资源操作  P操作
int P(int semid,int semno){
//定义一个操作的结构体变量
    struct sembuf buf;
    buf.sem_num = semno;          //要操作的灯的编号
    buf.sem_op = -1;               //表示申请资源操作
    buf.sem_flg = 0;            //如果没有资源,则阻塞等待

    //调用semop函数完成P操作
    if(semop(semid, &buf, 1) == -1)
    {
        perror("P error");
        return -1;
    }

    return 0;              //成功返回0
}

//释放信号灯资源操作  V操作
int V(int semid,int semno){
//定义一个操作的结构体变量
    struct sembuf buf;
    buf.sem_num = semno;          //要操作的灯的编号
    buf.sem_op = 1;               //表示释放资源操作
    buf.sem_flg = 0;            //如果没有资源,则阻塞等待

    //调用semop函数完成V操作
    if(semop(semid, &buf, 1) == -1)
    {
        perror("P error");
        return -1;
    }

    return 0;              //成功返回0

}

//信号灯集的删除
int del_sem(int semid){
//调用semc函数完成信号灯集的删除
    if(semctl(semid, 0, IPC_RMID, 0) == -1)
    {
        perror("delete error");
        return -1;
    }

    return 0;


}

2. 将共享内存和信号灯集完成两个进程间通信程序重新实现一下

shmsnd.c

#include <head.h>
#include "sem.h"

#define PAGE_SIZE 4096
int main(int argc, const char *argv[])
{
	//11.创建信号灯集
int semid =create_sem(2);
if(semid==-1){
	perror("create_sem error");
	return -1;
}

	//1.创建一个key值
	key_t key= ftok("/",'m');
	if(key==-1){
		perror("ftok error") ;
		return -1;
	}
	printf("key =%#x\n",key);
	//2.通过key值创建共享内存段
	int shmid= shmget(key,PAGE_SIZE,IPC_CREAT|0664);
	if(shmid==-1){
		perror("shmget error");
		return -1;
	}
	printf("shmid = %d\n",shmid);
	//3.将共享内存段映射到内存空间
	char *addr = shmat(shmid,NULL,0);
	if(addr==(void*)-1){
		perror("shmat error");
		return -1;
	}
	printf("addr=%p\n",addr);
	//4.使用共享内存段

	while(1){
		//22.P操作
		P(semid,0); //申请0号灯的资源
		printf("请输入>>>>");
		fgets(addr,PAGE_SIZE,stdin);
		addr[strlen(addr)-1]=0;
		//33.V操作
		V(semid,1); //释放1号灯的资源

		//判断退出条件
		if(strcmp(addr,"quit")==0){
			break;
		}
	}
	//5.取消映射
	if(shmdt(addr)==-1){
		perror("shmdt error");
		return -1;
	}
	//6.删除共享内存
	return 0;
}

shmrcv.c

#include <head.h>
#include "sem.h"

#define PAGE_SIZE 4096
int main(int argc, const char *argv[])
{

	//11.创建信号灯集
int semid =create_sem(2);
if(semid==-1){
	perror("create_sem error");
	return -1;
}

	//1.创建一个key值
	key_t key= ftok("/",'m');
	if(key==-1){
		perror("ftok error");
		return -1;
	}
	printf("key =%#x\n",key);
	//2.通过key值创建共享内存段
	int shmid= shmget(key,PAGE_SIZE,IPC_CREAT|0664);
	if(shmid==-1){
		perror("shmget error");
		return -1;
	}
	printf("shmid = %d\n",shmid);
	//3.将共享内存段映射到内存空间
	char *addr = shmat(shmid,NULL,0);
	if(addr==(void*)-1){
		perror("shmat error");
		return -1;
	}
	printf("addr=%p\n",addr);
	//4.使用共享内存段

	while(1){
		//22.P操作
		P(semid,1); //申请1号灯的资源

		printf("共享内存中的值是:%s\n",addr);
		//33.V操作
		V(semid,0); //释放0号灯的资源

		//判断退出条件
		if(strcmp(addr,"quit")==0){
			break;
		}
	}
	//5.取消映射
	if(shmdt(addr)==-1){
		perror("shmdt error");
		return -1;
	}

	//44.删除信号灯集
	del_sem(semid);
	//6.删除共享内存
	if(shmctl(shmid,IPC_RMID,NULL)==-1){
		perror("shmctl error");
		return -1;
	}
	return 0;
}

思维导图:

左值和右值:


    左值表示的是可以被识别和存储地址的表达式,它可以出现在赋值语句的左边。左值可以出现在赋值操作的目标位置。

右值表示的是无法识别和存储地址的表达式,它只能出现在赋值语句的右边。通常,右值在表达式计算后会生成一个具体的数值或结果。

如果两个指针同时指向一片地址,如果一个指针释放掉,另一个指针怎么知道已经释放了?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值