系统编程二:vfork+exec+进程通信方式管道+信号

一、从内存角度分析父子进程的资源问题

1、例子1

#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>


int main()
{
	//原本进程的代码
	int a = 100;
	printf("main\n");
	
	//创建一个子进程
	pid_t id = fork();
	if(id == -1)//出错
	{
		printf("fork error\n");
		return -1;
	}
	else if(id >0)//父进程
	{
		printf("parent:%d a addr:%p value:%d\n",getpid(),&a,a);		
	}
	else if(id == 0)//子进程
	{
		printf("child:%d a addr:%p value:%d\n",getpid(),&a,a);
		exit(0);//让子进程到这里就结束
	}
	
	printf("111\n");
	//阻塞等待 子进程退出
	wait(NULL);
	
	return 0;
}

结果:

结论:

父进程在fork时,会将父进程自己的空间拷贝一份给子进程。

2、例子2

#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>


int main()
{
	//原本进程的代码
	int a = 100;
	printf("main\n");
	
	//创建一个子进程
	pid_t id = fork();
	if(id == -1)//出错
	{
		printf("fork error\n");
		return -1;
	}
	else if(id >0)//父进程
	{
		a = 250; //父进程修改变量a的值
		printf("parent:%d a addr:%p value:%d\n",getpid(),&a,a);		
	}
	else if(id == 0)//子进程
	{
		sleep(1);
		printf("child:%d a addr:%p value:%d\n",getpid(),&a,a);
		exit(0);//让子进程到这里就结束
	}
	
	printf("111\n");
	//阻塞等待 子进程退出
	wait(NULL);
	
	return 0;
}

结果:

结论:

父进程 跟子进程 拥有相对独立的内存空间,互相不影响。

二、产生子进程的另一个函数 vfork

#include <sys/types.h>
    #include <unistd.h>

    pid_t vfork(void);

函数作用
    创建一个子进程,子进程 和 父进程 共享 数据段

特点:
    1、父进程与子进程共享数据段
    2、一定是 子进程先运行,而且是等子进程结束之后,父进程才开始运行
    3、当子进程调用exit之后,父进程才会往下执行
    4、你在引用的时候,最好尽快结束子进程

例子:

#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>


//int a = 100;

int main()
{
	//原本进程的代码
	//int a = 100; //a是局部变量,是栈区
	static int a = 100; //a是静态变量,存放在数据段
	printf("main\n");
	
	//使用vfork创建一个子进程,父进程与子进程共享数据段
	pid_t id = vfork();
	if(id == -1)//出错
	{
		printf("fork error\n");
		return -1;
	}
	else if(id >0)//父进程
	{
		
		printf("parent:%d a addr:%p value:%d\n",getpid(),&a,a);		
	}
	else if(id == 0)//子进程
	{		
		a = 250; //子进程修改变量a的值
		printf("child:%d a addr:%p value:%d\n",getpid(),&a,a);
		sleep(5);//这里就算延时5s,父进程也不会执行,父进程一定是等子进程结束之后才执行
		exit(0);//让子进程到这里就结束,接下来父进程就开始执行了
	}
	
	printf("111\n");
	//阻塞等待 子进程退出
	wait(NULL);
	
	return 0;
}	

三、exec函数族

        #include <unistd.h>

       extern char **environ;

       int execl(const char *path, const char *arg, ...); //变参函数
       int execlp(const char *file, const char *arg, ...);
       int execle(const char *path, const char *arg,
                  ..., char * const envp[]);
       int execv(const char *path, char *const argv[]);
       int execvp(const char *file, char *const argv[]);
       int execvpe(const char *file, char *const argv[],
                  char *const envp[]);

函数作用 
        在进程中加载新的程序,覆盖原有的代码,重新运行

参数
        path---》创建出子进程之后,你要让子进程执行哪个程序,将那个程序的路径+名字传递进来
                    比如创建出子进程之后,让他去执行另外一个程序  "./hello"
        arg--》执行程序时,需要的参数列表,以自身程序名字为开始,NULL作为结束标志
                    比如,你要执行 ./hello --》传递参数 123  ---> "he llo" 123 NULL
        
注意:只要进程 被exec族替换掉之后,在exec函数之后的代码都不会执行了

例子:

//创建一个子进程,子进程 去启动另外一个程序 hello ,并且传递一个参数"hai"给hello
#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>


//int a = 100;

int main()
{
	printf("main\n");
	
	pid_t id = fork();
	if(id == -1)//出错
	{
		printf("fork error\n");
		return -1;
	}
	else if(id >0)//父进程
	{
		
	}
	else if(id == 0)//子进程
	{
		//子进程去执行别的进程(应用程序) ./hello 
		execl("./hello","hello","hai",NULL);
		
		//execl后面的代码都不会执行了
		printf("chlid end\n");
		
		exit(0);//让子进程到这里就结束
	}
	
	printf("parent end\n");
	//阻塞等待 子进程退出
	wait(NULL);
	
	return 0;
}

练习1:

        写一个程序,这个程序创建一个子进程后,子进程打印haha,然后监控键盘,通过键盘的参数 去启动 另外一个程序,比如键盘输入 hello hai nihao ,就代表启动 hello程序,传递 hai nihao 到程序hello中,并且在程序hello把传递过来的参数打印出来。

#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>

/*
练习1:写一个程序,这个程序创建一个子进程后,
子进程打印haha,然后监控键盘,通过键盘的参数 去启动 另外一个程序,
比如键盘输入 hello hai nihao ,就代表启动 hello程序,
传递 hai nihao 到程序hello中,并且在程序hello把传递过来的参数打印出来
*/

int main()
{
	//printf("main\n");
	
	pid_t id = fork();
	if(id == -1)//出错
	{
		printf("fork error\n");
		return -1;
	}
	else if(id >0)//父进程
	{
		
	}
	else if(id == 0)//子进程
	{
		printf("child:%d haha\n",getpid());
		
		char str[10][256];
		bzero(str,sizeof(str));//清空数组的内存空间
		
		int i,cnt=0;
		printf("child 请输入数据:"); //hello hai nihao 
		
		while(1)
		{
			scanf("%s",str[cnt++]);
			char ch = getchar();
			if(ch == '\n')
				break;
		}
		
		//先把你要加载的程序的路径+名字拼接起来
		char pathName[1024]={0};
		sprintf(pathName,"./%s",str[0]); // ./hello
		
		//子进程去执行别的进程(应用程序) ./hello 
		switch(cnt-1)
		{
			case 1:
					execl(pathName,str[0],str[1],NULL);
					break;
			case 2:
					execl(pathName,str[0],str[1],str[2],NULL);
					break;					
		}	
	}
	
	printf("parent end\n");
	//阻塞等待 子进程退出
	wait(NULL);
	
	return 0;
}

四、进程之间的通信方式

1、为什么要实现进程之间的通信?

比如: 

./test  --->开启了一个叫做test的进程。
./project--->开启了一个叫做project的进程。

现在我们想要通过 test 去控制 project

2、在linux中,进程之间的通信方式有哪些?

(1)管道通信

        管道通信分为 无名管道  和 有名管道,管道是一个特殊的文件,进程通过将数据写入到管道中,另外一个进程从管道中将这个数据读取出来。

(2)信号

        通过信号去控制另外一个进程。

(3)消息队列 

(4)共享内存

以上通信有一个共同的特点:只能在同一台主机内部的进程使用。

五、无名管道 

1、什么是无名管道

        无名管道 只能作用于 亲缘之间的进程通信,无名管道相当于一个队列结构,fd[1]为写入端(入队),fd[0]为读出端(出队)。其中信息读出后即删除,再次读取时即为下一个信息。

2、接口函数

#include <unistd.h>

    int pipe(int pipefd[2]);

函数作用 
    创建无名管道文件。无名管道是一个特殊文件,不可由open函数创建。
参数 
    pipefd[2]两个成员 pipefd[0]和 pipefd[1],他们都是文件描述符。 管道有固定的读端 pipefd0]和固定的写端 pipefd[1]。

    pipefd[0]  ---读端  只能读取 数据  --读端文件描述符
    pipefd[1]  ---写端  只能写入 数据  --写端文件描述符
    
返回值 
    成功返回 0
    失败返回 -1 

例子1:创建一个无名管道文件,把他们的文件描述符都打印出来 fd[0]  和  fd[1]

//将无名管道的文件描述符打印出来
#include<stdio.h>
#include <unistd.h>


int main()
{
	int fd[2];
	//创建一个无名管道文件 ,创建成功之后 pipefd[0] 读端  pipefd[1] 写端
	pipe(fd);
	
	printf("fd[0]:%d fd[1]:%d\n",fd[0],fd[1]); //3  4
	
	
	return 0;
}

3、为什么 无名管道只能用于 亲缘之间的进程通信

        无名管道 在一个进程中被创建出来,只能通过继承的方式传递给子进程。也就是说子进程拷贝父进程的代码。

4、无名管道实现父子进程之间的通信

#include<stdio.h>
#include <unistd.h>


int main()
{
	int fd[2];
	//创建一个无名管道文件 ,创建成功之后 fd[0] 读端  fd[1] 写端
	pipe(fd); //注意,不可以使用open打开无名管道,因为它没有名字,创建的时候默认已经打开了
	
	//创建一个子进程 ,实现父进程与子进程的通信
	pid_t id = fork();
	if(id == -1)//出错
	{
		printf("fork error\n");
		return -1;
	}
	else if(id >0)//父进程
	{
		//给子进程发送数据,也就是说将数据写入 fd[1] 管道中
		while(1)
		{
			
			char sendbuf[1024] ={0};
			scanf("%s",sendbuf);
			write(fd[1],sendbuf,strlen(sendbuf));		
			
		}

	}
	else if(id == 0)//子进程
	{
		//sleep(1);
		//接收父进程的信息,也就是说从 读端 管道中 读取数据 fd[0]
		
		while(1)
		{
			char recvbuf[1024]={0};
			read(fd[0],recvbuf,sizeof(recvbuf));
			
			printf("child recvbuf:%s\n",recvbuf);			
		}

		exit(0);
	}
	
	wait(NULL);
	
	return 0;
}

六、有名管道

1、什么是有名管道文件?

        有名管道文件 是 一个有名字的管道文件。因为在linux下,所有的进程都是可以看到这个文件,所以有名管道作用的范围 是整个linux系统中任意的两个进程。

2、如何创建有名管道文件?(mkfifo)

#include <sys/types.h>
    #include <sys/stat.h>

    int mkfifo(const char *pathname, mode_t mode);

函数作用  
        创建一个有名管道文件 
        
参数 
        pathname --- 你要创建的这个管道文件 路径 + 名字 
        mode ---》权限  0777  0666

返回值 
    成功返回 0
    失败返回 -1 

3、判断文件是否存在

#include <unistd.h>

int access(const char *path, int amode);

函数作用:判断文件是否存在

参数 :
        path --》你要判断哪个文件 
        amode ---》F_OK  选择 判断文件的功能 

返回值  
        文件存在  0
        不存在  -1

例子1:(创建管道文件)

#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#define  FIFO_FILE  "/home/gec/fifo1"

int main()
{
	//先判断文件是否存在,如果存在则不用创建了
	if(access(FIFO_FILE, F_OK) == -1)//access 判断文件是否存在,如果不存在则返回 -1
	{
		//所以是不存在的时候才进来创建 
		//创建一个有名管道文件  
		if(mkfifo(FIFO_FILE,0777) == -1)
		{
			perror("mkfifo error");
			return -1;
		}	
	}
	
	
	return 0;
}

结果:

此时在家目录下就可以看到这个有名管道文件。

例子2:使用有名管道文件实现两个进程之间的通信。

//==========================进程1:作为写入端==============================

//06有名管道文件实现两个进程通信write.c

#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define  FIFO_FILE  "/home/gec/fifo1"

int main()
{
	//先判断文件是否存在,如果存在则不用创建了
	if(access(FIFO_FILE, F_OK) == -1)//access 判断文件是否存在,如果不存在则返回 -1
	{
		//创建一个有名管道文件  
		if(mkfifo("/home/gec/fifo2",0777) == -1)
		{
			perror("mkfifo error");
			return -1;
		}	
	}
	//发送数据 ,往有名管道文件中写入数据
	
	//1、打开有名管道文件
	int fd = open(FIFO_FILE,O_RDWR);
	if(fd == -1)
	{
		perror("open fifo error");
		return -1;
	}
	//2、写入数据 
	while(1)
	{
		printf("请输入数据:");
		char sendbuf[1024]={0};
		scanf("%s",sendbuf);
		
		write(fd,sendbuf,strlen(sendbuf));	

			
	}

	
	//3、关闭文件
	close(fd);
	return 0;
}
//=========================================进程2:读取数据=======================

//06有名管道文件实现两个进程通信read.c

#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define  FIFO_FILE  "/home/gec/fifo1"

int main()
{
	//先判断文件是否存在,如果存在则不用创建了
	if(access(FIFO_FILE, F_OK) == -1)//access 判断文件是否存在,如果不存在则返回 -1
	{
		//创建一个有名管道文件  
		if(mkfifo("/home/gec/fifo2",0777) == -1)
		{
			perror("mkfifo error");
			return -1;
		}	
	}
	
	//从管道文件中读取数据,并且打印出来
	
	//1、打开有名管道文件
	int fd = open(FIFO_FILE,O_RDWR);
	if(fd == -1)
	{
		perror("open fifo error");
		return -1;
	}
	//2、从管道文件中读取数据 
	while(1)
	{
		char recvbuf[1024]={0};
		read(fd,recvbuf,sizeof(recvbuf));
		
		printf("recvbuf:%s\n",recvbuf);		
		
	}
	//3、关闭文件
	close(fd);
	
	return 0;
}

总结:

1.管道是创建在内存中,进程结束空间释放,管道不复存在。
2.无名管道和有名管道都是半双工通信,实现双向通信需要建立两个管道。
3.无名管道是linux特殊文件,。
4.无名管道只用于父子进程之间,有名管道可用于任意两个进程之间。

4、练习:实现 两个进程之间可以 互聊

        使用有名管道实现两个进程之间 互相聊天 
        当 有一方 发出  "byebye" ,结束聊天

#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#include <stdlib.h>

#define  FIFO_FILE1  "/home/gec/fifo1"
#define  FIFO_FILE2  "/home/gec/fifo2"

int main(int argc,char*argv[])
{
	//先判断文件是否存在,如果存在则不用创建了
	if(access(FIFO_FILE1, F_OK) == -1)//access 判断文件是否存在,如果不存在则返回 -1
	{
		//创建一个有名管道文件  
		if(mkfifo(FIFO_FILE1,0777) == -1)
		{
			perror("mkfifo error");
			return -1;
		}	
	}
	//先判断文件是否存在,如果存在则不用创建了
	if(access(FIFO_FILE2, F_OK) == -1)//access 判断文件是否存在,如果不存在则返回 -1
	{
		//创建一个有名管道文件  
		if(mkfifo(FIFO_FILE2,0777) == -1)
		{
			perror("mkfifo error");
			return -1;
		}	
	}
	//发送数据 ,往有名管道文件中写入数据
	
	//创建一个子进程
	pid_t id =fork();
	
	if(id==-1)
	{
		perror("fork error");
	}	
	
	else if(id > 0)//父进程 ---专门 写入数据   FIFO_FILE2
	{	
		//1、打开有名管道文件
		int fd1 = open(FIFO_FILE2,O_RDWR);
		if(fd1 == -1)
		{
			perror("open fifo error");
			return -1;
		}
		//2、写入数据 
		while(1)
		{
			char endbuf[256]="byby";
			printf("请输入数据:");
			char sendbuf[1024]={0};
			scanf("%s",sendbuf);
			
			write(fd1,sendbuf,strlen(sendbuf));		
			if(strcmp(endbuf,sendbuf)==0) //退出条件,也就是如果输入了 byby ,那么退出
			{
				
				break;
			}
			

		}
		printf("父进程退出,通知子进程,让子进程也退出\n");
		
		char cmd[1024]={0};
		sprintf(cmd,"killall -SIGKILL %s",argv[0]);
		system(cmd);
		
		//3、关闭文件
		close(fd1);
	}
	
	else if(id == 0) //子进程 ---读取数据   FIFO_FILE1
	{
		//1、打开有名管道文件
		int fd2 = open(FIFO_FILE1,O_RDWR);
		if(fd2 == -1)
		{
			perror("open fifo error");
			return -1;
		}
		//2、读取数据 
		while(1)
		{
			char endbuf[256]="byby";
			char recvbuf[1024]={0};
			read(fd2,recvbuf,sizeof(recvbuf));	
			printf("recvbuf:%s\n",recvbuf);		
			if(strcmp(endbuf,recvbuf)==0)
				break;		
		}
		
		//3、关闭文件
		close(fd2);
		exit(0);
	}
	
	
	return 0;
}
#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#include <stdlib.h>
#define  FIFO_FILE1  "/home/gec/fifo1"
#define  FIFO_FILE2  "/home/gec/fifo2"
int main(int argc,char*argv[])
{
	//先判断文件是否存在,如果存在则不用创建了
	if(access(FIFO_FILE1, F_OK) == -1)//access 判断文件是否存在,如果不存在则返回 -1
	{
		//创建一个有名管道文件  
		if(mkfifo(FIFO_FILE1,0777) == -1)
		{
			perror("mkfifo error");
			return -1;
		}	
	}
	//先判断文件是否存在,如果存在则不用创建了
	if(access(FIFO_FILE2, F_OK) == -1)//access 判断文件是否存在,如果不存在则返回 -1
	{
		//创建一个有名管道文件  
		if(mkfifo(FIFO_FILE2,0777) == -1)
		{
			perror("mkfifo error");
			return -1;
		}	
	}
	//从管道文件中读取数据,并且打印出来
	pid_t id =fork();
	if(id==-1)
	{
		perror("fork error");
	}	
	else if(id > 0) //父进程  --写入数据   FIFO_FILE1
	{
	
		//发送数据 ,往有名管道文件中写入数据
		
		//1、打开有名管道文件
		int fd1 = open(FIFO_FILE1,O_RDWR);
		if(fd1 == -1)
		{
			perror("open fifo error");
			return -1;
		}
		//2、写入数据 
		while(1)
		{
			char endbuf[256]="byby";
			printf("请输入数据:");
			char sendbuf[1024]={0};
			scanf("%s",sendbuf);
			
			write(fd1,sendbuf,strlen(sendbuf));		
			if(strcmp(endbuf,sendbuf)==0)
			{
				wait(NULL);
				break;
			}
		}
		printf("父进程退出\n");
		//3、关闭文件
		close(fd1);
	
	}	
	
	else if(id == 0) //子进程  读取 数据 FIFO_FILE2
	{
		//1、打开有名管道文件
		int fd2 = open(FIFO_FILE2,O_RDWR);
		if(fd2 == -1)
		{
			perror("open fifo error");
			return -1;
		}
		//2、读取数据 
		while(1)
		{
			char endbuf[256]="byby";
			char recvbuf[1024]={0};
			read(fd2,recvbuf,sizeof(recvbuf));
			
			printf("recvbuf:%s\n",recvbuf);		
			if(strcmp(endbuf,recvbuf)==0)
			{		
				break;
			}
			
		}
		printf("子进程退出,给父进程发送信号,通知父进程也退出\n");
		//子进程发送信号杀死父进程 
		char cmd[1024]={0};
		sprintf(cmd,"killall -SIGKILL %s",argv[0]);
		
		system(cmd);
		
		//3、关闭文件
		close(fd2);
		exit(0);
	}	
	

	return 0;
}

七、进程通信方式之一 ----信号 (异步通信方式)

1、在linux中,有哪些信号?

如:

19) SIGSTOP

19: 表示信号值
SIGSTOP :信号的名字,其实一个宏

2、分类

1 - 31 为 非实时信号 ,每个信号会有一个默认的执行动作
34-64 为 实时信号

3、常用的信号

2) SIGINT --》ctrl + C

9) SIGKILL --->停止信号 

18) SIGCONT --继续信号
19) SIGSTOP --暂停信号 ,比如当前想要暂停播放音乐  实际上就是向当前播放器这个进程 发送这个 暂停信号

4、在linux中,这些信号到底是由谁发出来的?

1)由系统发出来的。

14) SIGALRM ---》当在程序中调用了定时器alarm()时,如果到点了,就会自动发出这个信号。

2)信号还可以由用户来发送。
    kill / killall
 

5、用户如何发送信号给进程?

方法一:

1)查看当前目标进程的PID号。--》ps -ef 

gec       5088  4592  0 01:59 pts/2    00:00:00 ./hello


2)通过kill命令 发送 9号信号给该进程 ,杀死这个进程。

kill -9 5088
kill -SIGKILL 5088


方法二: 

直接通过killall命令给进程名字发送信号 

killall -9 hello 
killall -SIGKILL hello 
killall -KILL hello
 

八、在开发板中播放音乐   ---1.mp3文件 ----音频格式的数据文件

        使用音频播放器 madplay 

1、该音频播放器在开发板中的位置

[root@GEC6818 ~]#which madplay
/usr/bin/madplay

2、查看该播放器的使用手册

[root@GEC6818 ~]#madplay -h
Usage: madplay [OPTIONS] FILE [...]   [OPTIONS] -可以省略
Decode and play MPEG audio FILE(s).

3、如何播放音乐呢?

        madplay  + 音乐的路径名

[root@GEC6818 /IOT/mp3]#madplay  left.mp3   -播放 left.mp3音乐
MPEG Audio Decoder 0.15.2 (beta) - Copyright (C) 2000-2004 Robert Leslie et al.
        Encoder: Lavf52.24.1
142 frames decoded (0:00:03.7), +2.8 dB peak amplitude, 900 clipped samples

4、如何在代码中播放呢?

        char cmd[] = "madplay  left.mp3";
        system(cmd);

5、如何控制音乐的状态呢?

//暂停音乐实际上就是暂停音乐播放器这个进程
暂停音乐: killall -SIGSTOP  madplay
继续播放音乐: killall -SIGCONT  madplay

system("killall -SIGSTOP  madplay");
 

九、制作一个简单的音乐播放器

必须要有界面,实现 暂停、播放、停止、继续

#include<stdio.h>
#include <stdlib.h>

enum {
	Ready,//准备状态 0
	Player, // 1  正在播放 
	Stop,// 2
	Continue,// 3
	Kill// 4
};

int MusicStatus = Ready;//表示音乐的状态

int playerMusic()
{
	if(MusicStatus == Ready || MusicStatus == Kill)//如果是准备状态 或者是停止状态 才 播放音乐
	{
		printf("playerMusic\n");
		char cmd[] = "madplay test.mp3 &";//&表示的是让音乐在后台播放
		system(cmd);
		
		//更新音乐的状态
		MusicStatus = Player;			
	}	
}
int stopMusic()//暂停音乐 
{
	//只能是在正在播放的状态才可以暂停
	if(MusicStatus == Player)
	{
		printf("stopMusic\n");
		char cmd[] = "killall -SIGSTOP madplay";
		system(cmd);
		
		MusicStatus = Stop;			
	}

}
int continueMusic()//继续播放
{
	//只能是暂停的时候才可以 继续播放 
	if(MusicStatus == Stop)
	{
		printf("continueMusic\n");
		char cmd[] = "killall -SIGCONT madplay";
		system(cmd);

		MusicStatus = Continue;		
	}

}
int killMusic()//停止音乐
{
	//什么时候可以停止音乐呢?  Player,  Stop  Continue
	if(MusicStatus == Player || MusicStatus == Stop || MusicStatus == Continue)
	{
		printf("killMusic\n");
		char cmd[] = "killall -SIGKILL madplay";
		system(cmd);

		MusicStatus = Kill;					
	}

}

int main()
{
	while(1)
	{
		int mode=-1;
		printf("[1]播放音乐 [2]暂停音乐 [3]继续播放 [4]停止音乐:");
		scanf("%d",&mode);
		
		switch(mode)
		{
			case Player://播放音乐
					playerMusic();
					break;
			case Stop://暂停音乐
					stopMusic();
					break;
			case Continue://继续播放
					continueMusic();
					break;
			case Kill://停止音乐
					killMusic();
					break;					
		}		
		
	}

	
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值