安全1601_沈香港_16281077_操作系统lab3

安全1601_沈香港_16281077_操作系统lab3

说明:本实验有参考孙汉武同学实验

TASK1

1.1 代码

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<fcntl.h>
int main()
{
	sem_t *P1_signal,*P2_signal,*P3_signal;
	P1_signal=sem_open("P1_signal",O_CREAT,0666,0);
	P2_signal=sem_open("P2_signal",O_CREAT,0666,0);
	P3_signal=sem_open("P3_signal",O_CREAT,0666,0);
        pid_t p2,p3,p4;//主函数的进程为P1
	p2=fork();//创建进程P2
	if(p2<0)	
	{
		perror("创建进程p2出错\n");
	}
	if(p2==0)//当前运行进程为p2
	{
		sem_wait(P1_signal);
		printf("I am the process P2\n");
		sem_post(P1_signal);
		sem_post(P2_signal);//p4进程条件
	}
	if(p2>0)//当前运行进程为P1
	{
		p3=fork();//创建进程p3
		if(p3<0)	
		{
			perror("创建进程p出错!");
		}
		if(p3==0)//当前运行进程为P3
		{
			sem_wait(P1_signal);
			printf("I am the process P3\n");
			sem_post(P1_signal);
			sem_post(P3_signal);//P4进程条件
		}
		if(p3>0)//当前运行进程为P1
		{
			printf("I am the process P1\n");
			sem_post(P1_signal);
			p4=fork();//创建进程P4
			if(p4<0)	
			{
				perror("创建进程p4出错\n");
			}
			if(p4==0)
			{
				sem_wait(P2_signal);
				sem_wait(P3_signal);
				printf("I am the process P4\n");
				sem_post(P2_signal);
				sem_post(P3_signal);
			}
		}
	}
	sem_close(P1_signal);
	sem_close(P2_signal);
	sem_close(P3_signal);
	sem_unlink("P1_signal");
	sem_unlink("P2_signal");
	sem_unlink("P3_signal");
	return 0;
}

1.2 原理

前趋图

在这里插入图片描述

前驱关系:
   P1-->P2、P1-->P3、P2-->P4、P3-->P4

1.3实验结果

在这里插入图片描述

1.4分析

测试的实验结果中出现两种执行顺序,由于P1是P2和P3的前驱,所以P1一定会在P2和P3之前执行,但是P2和P3是互斥关系,这两个进程谁先获得P1产生的信号量谁就先执行另一个进程等待。最后等P2和P3都执行完了再执行P4,所以会出现上面的两种执行顺序。

TASK2

2.1.1代码

q2_1.c

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
void pthread_yield();
int ticketCount=1000;
void *SaleThread(void *arg)
{
	int num,temp,i;
	num=atoi(arg);
	for(i=0;i<num;i++)
	{
		temp=ticketCount;
		pthread_yield();//强制线程频繁切换
		temp=temp-1;
		pthread_yield();//强制线程频繁切换
		ticketCount=temp;
	}
}

void *RefundThread(void *arg)
{
	int num,temp,i;
	num=atoi(arg);
	for(i=0;i<num;i++)
	{
		temp=ticketCount;
		pthread_yield();//强制线程频繁切换
		temp=temp+1;
		pthread_yield();//强制线程频繁切换
		ticketCount=temp;
	}
}
int main(int argc,char *argv[])
{
	if(argc!=3)
	{
		printf("请正确输入参数!\n");
		exit(0);
	}
	printf("火车票余票初始值:%d\n",ticketCount);
	pthread_t p1,p2;
	pthread_create(&p1,NULL,SaleThread,argv[1]);
	pthread_create(&p2,NULL,RefundThread,argv[2]);
	pthread_join(p1,NULL);
	pthread_join(p2,NULL);
	printf("火车票余票最终值:%d\n",ticketCount);
	return 0;
}
2.1.2程序解释

1.模拟售票的线程SaleThread和模拟退票的线程RefundThread,两个进程并发执行,无任何的同步机制。
2.模拟票数变量ticketCount是全局变量
3.程序运行包括两个参数,一个是售票数量,一个是退票数量

2.1.2 运行结果

在这里插入图片描述
多次测试结果运行表明,实验现象为

当售票数量大于退票数量的时候,最终票数等于总票数减去售票数
当售票数量小于退票数量的时候,最终票数等于总票数加上退票数

2.2.1实验代码

q2_2.c

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
void pthread_yield();
int ticketCount=1000;
sem_t *mutex=NULL;
void *SaleThread(void *arg)
{
	int num,temp,i;
	num=atoi(arg);
       for(i=0;i<num;i++){
		sem_wait(mutex);
		temp=ticketCount;
		pthread_yield();//强制线程频繁切换
		temp=temp-1;
		pthread_yield();//强制线程频繁切换
		ticketCount=temp;
		sem_post(mutex);
	}
}

void *RefundThread(void *arg)
{
	int num,temp,i;
	num=atoi(arg);
	for(i=0;i<num;i++)
	{
		sem_wait(mutex);
		temp=ticketCount;
		pthread_yield();//强制线程频繁切换
		temp=temp+1;
		pthread_yield();//强制线程频繁切换
		ticketCount=temp;
		sem_post(mutex);
        }
}
int main(int argc,char *argv[])
{
	if(argc!=3)
	{
		printf("请正确输入参数!\n");
		exit(0);
	}
	mutex=sem_open("mutex",O_CREAT,0666,1);
	printf("火车票余票初始值:%d\n",ticketCount);
	pthread_t p1,p2;
	pthread_create(&p1,NULL,SaleThread,argv[1]);
	pthread_create(&p2,NULL,RefundThread,argv[2]);
	pthread_join(p1,NULL);
	pthread_join(p2,NULL);
	printf("火车票余票最终值:%d\n",ticketCount);
	sem_close(mutex);
	sem_unlink("mutex");
	return 0;
}

2.2.2程序说明

通过信号量mutex的控制,让售票线程和退票线程一次只能执行一个,在一个没有执行完成之前另一个不能进入执行。
mutex初始值为设置为1,每次只允许一个线程操作ticketCount这个数据

2.2.3运行结果

在这里插入图片描述

2.2.4实验结果

增加了同步机制之后的多线程并发程序有效的解决了脏数据的读取问题

TASK3

3.1实验代码

q3.c

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
char buf[10];
sem_t *empty=NULL;//缓存区未写入数量
sem_t *full=NULL;//缓存区写入数量
void *producer(void *arg)
{
	
	for(int i=0;i<10;i++)
	{
		sem_wait(empty);
		scanf("%c",&buf[i]);
		sem_post(full);
		if(i==9)
		{
			i=-1;
		}
	}	
}
void *comsumer(void *arg)
{
	for(int i=0;i<10;i++)
	{
		sem_wait(full);
		printf("输出:%c\n",buf[i]);
		sem_post(empty);
		sleep(1);
		if(i==9)
		{
			i=-1;		
		}
	}	
}

int main(int argc,char *argv[])
{
	empty=sem_open("_empty",O_CREAT,0666,10);
	full=sem_open("_full",O_CREAT,0666,0);
	pthread_t p1,p2;
	pthread_create(&p1,NULL,producer,NULL);
	pthread_create(&p2,NULL,comsumer,NULL);
	pthread_join(p1,NULL);
	pthread_join(p2,NULL);
	sem_close(empty);
	sem_close(full);
	sem_unlink("_empty");
	sem_unlink("_full");
	return 0;
}

3.2程序解释

producer是输入线程调用的函数,comsumer是输出线程调用的函数
empty信号量用于保证输入线程在写入数据到缓存的时候缓存中还有空余的位置,保证写入线程后写入的数据不会把前面写入但是为输出的数据给覆盖掉,其初始值为10,表示最开始缓存中有10个空余的位置供给写入线程写入数据;full信号量是用于保证输出线程有数据输出,避免在写入线程还没有写入数据的情况下输出线程输出随机数据,其初始值为0,表示初始状态下缓存中没有数据可以输出
输入线程在写入一个数据前要等待empty信号量,进入后便消耗一个信号量;完成写入数据操作之后post一个full信号量,通知输出线程输出数据
输出线程在输出一个数据之前哟啊等待full信号量,进出输出操作后便消耗一个full信号量;完成输出操作后post一个empty信号量,通知写入线程缓存又多一个空余位置以供写入数据

3.3三种实验结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.4实验结果分析

输入数据不大于10个字符的时候,由于empty的信号量初始值为10,所以输入进程会一直连续不断的向缓存中写入数据,每写入一个数据,便post一个full信号量,输出线程便能按序输出字符。
输入数据大于10个字符的时候,由于empty的初始值为10,所以输入的字符中开始的时候只有前10个字符被写入缓存中,其他的在I/O缓冲区等待输入,当输出线程接收到输入线程post的信号量的时候便会开始输出,每输出一个字符便会post一个empty信号量,当输入线程接收到empty信号量的时候有开始从I/O缓冲区读取数据写入到缓存中。

TASK4

4.1.1内存共享

1实验代码
Sender.c

/*
 * Filename: Sender.c
 * Description: 
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>

int main(int argc, char *argv[])
{
    key_t  key;
    int shm_id;
    int sem_id;
    int value = 0;
    //1.Product the key
    key = ftok(".", 0xFF);
    //2. Creat semaphore for visit the shared memory
    sem_id = semget(key, 1, IPC_CREAT|0644);
    if(-1 == sem_id)
    {
        perror("semget");
        exit(EXIT_FAILURE);
    }
    //3. init the semaphore, sem=0
    if(-1 == (semctl(sem_id, 0, SETVAL, value)))
    {
        perror("semctl");
        exit(EXIT_FAILURE);
    }
    //4. Creat the shared memory(1K bytes)
    shm_id = shmget(key, 1024, IPC_CREAT|0644);
    if(-1 == shm_id)
    {
        perror("shmget");
        exit(EXIT_FAILURE);
    }
    //5. attach the shm_id to this process
    char *shm_ptr;
    shm_ptr = shmat(shm_id, NULL, 0);
    if(NULL == shm_ptr)
    {
        perror("shmat");
        exit(EXIT_FAILURE);
    }
    //6. Operation procedure
    struct sembuf sem_b;
    sem_b.sem_num = 0;      //first sem(index=0)
    sem_b.sem_flg = SEM_UNDO;
    sem_b.sem_op = 1;           //Increase 1,make sem=1
    
    while(1)
    {
        if(0 == (value = semctl(sem_id, 0, GETVAL)))
        {
            printf("\nNow, snd message process running:\n");
            printf("\tInput the snd message:  ");
            scanf("%s", shm_ptr);

            if(-1 == semop(sem_id, &sem_b, 1))
            {
                perror("semop");
                exit(EXIT_FAILURE);
            }
        }
        //if enter "end", then end the process
        if(0 == (strcmp(shm_ptr ,"end")))
        {
            printf("\nExit sender process now!\n");
            break;
        }
    }
    shmdt(shm_ptr);
    return 0;
}

Receiver.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>

int main(int argc, char *argv[])
{
    key_t  key;
    int shm_id;
    int sem_id;
    int value = 0;
    //1.Product the key
    key = ftok(".", 0xFF);
    //2. Creat semaphore for visit the shared memory
    sem_id = semget(key, 1, IPC_CREAT|0644);
    if(-1 == sem_id)
    {
        perror("semget");
        exit(EXIT_FAILURE);
    }
    //3. init the semaphore, sem=0
    if(-1 == (semctl(sem_id, 0, SETVAL, value)))
    {
        perror("semctl");
        exit(EXIT_FAILURE);
    }
    //4. Creat the shared memory(1K bytes)
    shm_id = shmget(key, 1024, IPC_CREAT|0644);
    if(-1 == shm_id)
    {
        perror("shmget");
        exit(EXIT_FAILURE);
    }
    //5. attach the shm_id to this process
    char *shm_ptr;
    shm_ptr = shmat(shm_id, NULL, 0);
    if(NULL == shm_ptr)
    {
        perror("shmat");
        exit(EXIT_FAILURE);
    }

    //6. Operation procedure
    struct sembuf sem_b;
    sem_b.sem_num = 0;      //first sem(index=0)
    sem_b.sem_flg = SEM_UNDO;
    sem_b.sem_op = -1;           //Increase 1,make sem=1
    
    while(1)
    {
        if(1 == (value = semctl(sem_id, 0, GETVAL)))
        {
            printf("\nNow, receive message process running:\n");
            printf("\tThe message is : %s\n", shm_ptr);

            if(-1 == semop(sem_id, &sem_b, 1))
            {
                perror("semop");
                exit(EXIT_FAILURE);
            }
        }
        //if enter "end", then end the process
        if(0 == (strcmp(shm_ptr ,"end")))
        {
            printf("\nExit the receiver process now!\n");
            break;
        }
    }
    shmdt(shm_ptr);
    //7. delete the shared memory
    if(-1 == shmctl(shm_id, IPC_RMID, NULL))
    {
        perror("shmctl");
        exit(EXIT_FAILURE);
    }
    //8. delete the semaphore
    if(-1 == semctl(sem_id, 0, IPC_RMID))
    {
        perror("semctl");
        exit(EXIT_FAILURE);
    }
    return 0;
}

4.1.2执行结果

在这里插入图片描述

4.1.3删除互斥访问

Sender_2.c:

/*
 * Filename: Sender.c
 * Description: 
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>

int main(int argc, char *argv[])
{
    key_t  key;
    int shm_id;
    int sem_id;
    int value = 0;
    //1.Product the key
    key = ftok(".", 0xFF);
    //2. Creat semaphore for visit the shared memory
    sem_id = semget(key, 1, IPC_CREAT|0644);
    if(-1 == sem_id)
    {
        perror("semget");
        exit(EXIT_FAILURE);
    }
    //3. init the semaphore, sem=0
    if(-1 == (semctl(sem_id, 0, SETVAL, value)))
    {
        perror("semctl");
        exit(EXIT_FAILURE);
    }
    //4. Creat the shared memory(1K bytes)
    shm_id = shmget(key, 1024, IPC_CREAT|0644);
    if(-1 == shm_id)
    {
        perror("shmget");
        exit(EXIT_FAILURE);
    }
    //5. attach the shm_id to this process
    char *shm_ptr;
    shm_ptr = shmat(shm_id, NULL, 0);
    if(NULL == shm_ptr)
    {
        perror("shmat");
        exit(EXIT_FAILURE);
    }
    //6. Operation procedure
    struct sembuf sem_b;
    sem_b.sem_num = 0;      //first sem(index=0)
    sem_b.sem_flg = SEM_UNDO;
    sem_b.sem_op = 1;           //Increase 1,make sem=1
    
    while(1)
    {
            printf("\nNow, snd message process running:\n");
            printf("\tInput the snd message:  ");
            scanf("%s", shm_ptr);
        //if enter "end", then end the process
        if(0 == (strcmp(shm_ptr ,"end")))
        {
            printf("\nExit sender process now!\n");
            break;
        }
    }
}

Receiver_2.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>

int main(int argc, char *argv[])
{
    key_t  key;
    int shm_id;
    int sem_id;
    int value = 0;
    //1.Product the key
    key = ftok(".", 0xFF);
    //2. Creat semaphore for visit the shared memory
    sem_id = semget(key, 1, IPC_CREAT|0644);
    if(-1 == sem_id)
    {
        perror("semget");
        exit(EXIT_FAILURE);
    }
    //3. init the semaphore, sem=0
    if(-1 == (semctl(sem_id, 0, SETVAL, value)))
    {
        perror("semctl");
        exit(EXIT_FAILURE);
    }
    //4. Creat the shared memory(1K bytes)
    shm_id = shmget(key, 1024, IPC_CREAT|0644);
    if(-1 == shm_id)
    {
        perror("shmget");
        exit(EXIT_FAILURE);
    }
    //5. attach the shm_id to this process
    char *shm_ptr;
    shm_ptr = shmat(shm_id, NULL, 0);
    if(NULL == shm_ptr)
    {
        perror("shmat");
        exit(EXIT_FAILURE);
    }

    //6. Operation procedure
    struct sembuf sem_b;
    sem_b.sem_num = 0;      //first sem(index=0)
    sem_b.sem_flg = SEM_UNDO;
    sem_b.sem_op = -1;           //Increase 1,make sem=1
    
    while(1)
    {
            printf("\nNow, receive message process running:\n");
            printf("\tThe message is : %s\n", shm_ptr);
        //if enter "end", then end the process
        if(0 == (strcmp(shm_ptr ,"end")))
        {
            printf("\nExit the receiver process now!\n");
            break;
        }
        sleep(3);
    }
    shmdt(shm_ptr);
    //7. delete the shared memory
    if(-1 == shmctl(shm_id, IPC_RMID, NULL))
    {
        perror("shmctl");
        exit(EXIT_FAILURE);
    }
    //8. delete the semaphore
    if(-1 == semctl(sem_id, 0, IPC_RMID))
    {
        perror("semctl");
        exit(EXIT_FAILURE);
    }
    return 0;
}

执行结果为
在这里插入图片描述

4.1.4打印共享内存地址

结果在这里插入图片描述
看到两个进程中共享内存地址不一样

4.2.1管道通信

(1)无名管道
1实验源码
pipe.c:

#include <stdio.h>
#include <unistd.h>     //for pipe()
#include <string.h>     //for memset()
#include <stdlib.h>     //for exit()
int main()
{
    int fd[2];
    char buf[20];
    if(-1 == pipe(fd))
    {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    write(fd[1], "hello,world", 12);
    memset(buf, '\0', sizeof(buf));
    read(fd[0], buf, 12);
    printf("The message is: %s\n", buf);
    return 0;
}

2实验结果
在这里插入图片描述
3无名管道同步机制验证
pipe_2.c:

#include <stdio.h>
#include <unistd.h>     //for pipe()
#include <string.h>     //for memset()
#include <stdlib.h>     //for exit()
int main()
{
    int fd[2];
    char buf[200]={0};
	pid_t child;
    //创建管道
	if(-1 == pipe(fd))
    {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
	//创建子进程
	child=fork();
	if(child==-1)
	{
		perror("fork");
		exit("EXIT_FAILURE");
	}
	if(child==0)
	{
		//关闭子进程中不需要的写描述符
		close(fd[1]);
		while(1)
		{
			if(read(fd[0],buf,sizeof(buf))>0)
					printf("子进程接收的消息是:%s\n",buf);
			else
					printf("子进程:管道中没有数据\n");
			sleep(2);		
			if(strcmp(buf,"end")==0)
					break;
			memset(buf,0,sizeof(buf));
		}
	}
	if(child>0)
	{
		close(fd[0]);
		while(1)
		{
			printf("父进程中-请输入消息:");
			scanf("%s",buf);
			write(fd[1],buf,strlen(buf));
			if(strcmp(buf,"end")==0)
				break;
		}	
	}
    return 0;
}

4无名管道同步机制实验现象
在这里插入图片描述
可以看到输出进程是按照输入进程输入的顺序输出数据,并且当输入进程没有数据输入,即管道中没有数据的时候,输出进程会阻塞。因此无名管道通信系统调用的时候已经实现了同步机制
(2)有名管道
1实验代码
fifo_send.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <fcntl.h>
#define FIFO "./my_fifo"

int main()
{
    char buf[] = "hello,world";
    //1. check the fifo file existed or not
    int ret;
    ret = access(FIFO, F_OK);
    if(ret != 0)    //file /tmp/my_fifo existed
    {
    	if(-1 == mkfifo(FIFO, 0766))
    	{
    	    perror("mkfifo");
    	    exit(EXIT_FAILURE);
    	}
    }

    //3.Open the fifo file
    int fifo_fd;
    fifo_fd = open(FIFO, O_WRONLY);
    if(-1 == fifo_fd)
    {
        perror("open");
        exit(EXIT_FAILURE);

    }
    //4. write the fifo file
    int num = 0;
    num = write(fifo_fd, buf, sizeof(buf));
    if(num < sizeof(buf))
    {
        perror("write");
        exit(EXIT_FAILURE);
    }
    printf("write the message ok!\n");

    close(fifo_fd);

    return 0;
}

fifo_rcv.c:

/*
 *File: fifo_rcv.c
 */
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <fcntl.h>


#define FIFO "./my_fifo"

int main()
{
    char buf[20] ;
    memset(buf, '\0', sizeof(buf));

    //`. check the fifo file existed or not
    int ret;
    ret = access(FIFO, F_OK);
    if(ret != 0)    //file /tmp/my_fifo existed
    {
        if(-1==mkfifo(FIFO,0766))
        {
            perror("mkfifo"); 
            exit("EXIT_FAILURE");
        }
    }

//	2.Open the fifo file
    int fifo_fd;
    fifo_fd = open(FIFO, O_RDONLY);
    if(-1 == fifo_fd)
    {
        perror("open");
        exit(EXIT_FAILURE);
    }
    //4. read the fifo file
    int num = 0;
    num = read(fifo_fd, buf, sizeof(buf));
    printf("Read %d words: %s\n", num, buf);
    close(fifo_fd);
    return 0;
}

2实验现象
在这里插入图片描述
在这里插入图片描述
在仅仅只运行fifo_send进程的时候,没有任何输出,进程一直阻塞,直到fifo_rcv进程运行,两个进程才开始输出信息。
当写进程和读进程都设置成阻塞状态的时候,不论先执行那个进程,先执行的进程都会阻塞等待,待另一个进程执行后两个进程才正常执行。

4.3.1消息队列

1实验代码
Server.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <signal.h>

#define BUF_SIZE 128

//Rebuild the strcut (must be)
struct msgbuf
{
    long mtype;
    char mtext[BUF_SIZE];
};
int main(int argc, char *argv[])
{
    //1. creat a mseg queue
    key_t key;
    int msgId;
    
    key = ftok(".", 0xFF);
    msgId = msgget(key, IPC_CREAT|0644);
    if(-1 == msgId)
    {
        perror("msgget");
        exit(EXIT_FAILURE);
    }

    printf("Process (%s) is started, pid=%d\n", argv[0], getpid());

    while(1)
    {
        alarm(0);
        alarm(600);     //if doesn't receive messge in 600s, timeout & exit
        struct msgbuf rcvBuf;
        memset(&rcvBuf, '\0', sizeof(struct msgbuf));
        msgrcv(msgId, &rcvBuf, BUF_SIZE, 1, 0);                
        printf("Receive msg: %s\n", rcvBuf.mtext);
        
        struct msgbuf sndBuf;
        memset(&sndBuf, '\0', sizeof(sndBuf));

        strncpy((sndBuf.mtext), (rcvBuf.mtext), strlen(rcvBuf.mtext)+1);
        sndBuf.mtype = 2;

        if(-1 == msgsnd(msgId, &sndBuf, strlen(rcvBuf.mtext)+1, 0))
        {
            perror("msgsnd");
            exit(EXIT_FAILURE);
        }
            
        //if scanf "end~", exit
        if(!strcmp("end~", rcvBuf.mtext))
             break;
    }     
    printf("THe process(%s),pid=%d exit~\n", argv[0], getpid());
    return 0;
}

Client.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <signal.h>

#define BUF_SIZE 128

//Rebuild the strcut (must be)
struct msgbuf
{
    long mtype;
    char mtext[BUF_SIZE];
};


int main(int argc, char *argv[])
{
    //1. creat a mseg queue
    key_t key;
    int msgId;
    
    printf("THe process(%s),pid=%d started~\n", argv[0], getpid());

    key = ftok(".", 0xFF);
    msgId = msgget(key, IPC_CREAT|0644);
    if(-1 == msgId)
    {
        perror("msgget");
        exit(EXIT_FAILURE);
    }

    //2. creat a sub process, wait the server message
    pid_t pid;
    if(-1 == (pid = fork()))
    {
        perror("vfork");
        exit(EXIT_FAILURE);
    }

    //In child process
    if(0 == pid)
    {
        while(1)
        {
            alarm(0);
            alarm(100);     //if doesn't receive messge in 100s, timeout & exit
            struct msgbuf rcvBuf;
            memset(&rcvBuf, '\0', sizeof(struct msgbuf));
            msgrcv(msgId, &rcvBuf, BUF_SIZE, 2, 0);                
            printf("Server said: %s\n", rcvBuf.mtext);
        }
        
        exit(EXIT_SUCCESS);
    }

    else    //parent process
    {
        while(1)
        {
            usleep(100);
            struct msgbuf sndBuf;
            memset(&sndBuf, '\0', sizeof(sndBuf));
            char buf[BUF_SIZE] ;
            memset(buf, '\0', sizeof(buf));
            
            printf("\nInput snd mesg: ");
            scanf("%s", buf);
            
            strncpy(sndBuf.mtext, buf, strlen(buf)+1);
            sndBuf.mtype = 1;

            if(-1 == msgsnd(msgId, &sndBuf, strlen(buf)+1, 0))
            {
                perror("msgsnd");
                exit(EXIT_FAILURE);
            }            
            //if scanf "end~", exit
            if(!strcmp("end~", buf))
                break;
        }
        
        printf("THe process(%s),pid=%d exit~\n", argv[0], getpid());
    }
    return 0;
}

2程序运行结果
在这里插入图片描述

TASK5

未完成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值