1.掌握双向循环链表,对指针,结构体,动态分配内存等C语言要求较高
2.掌握多进程编程,以及共享内存通信相关方面的内容
/*
* mp3播放器控制程序
* 功能:
k1:播放、暂停
k2:停止播放
k3:上一首
k4:下一首
* 附加:歌曲自动循环播放
*
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*共享内存申请标记*/
#define PERM S_IRUSR|S_IWUSR
/*双向循环列表:存放歌曲名*/
struct song
{
char songname[20];
struct song *prev;
struct song *next;
};
/*孙子进程id号*/
pid_t gradchild;
/*子进程id号*/
pid_t pid;
/*共享内存描述标记*/
int shmid;
char *p_addr;
/*播放标记*/
int first_key=1;
int play_flag=0;
/*************************************************
Function name: play
Parameter : struct song *
Description : 播放函数
Return : void
Argument : void
Autor & date : ada 09,12,07
**************************************************/
#if 1
void play(struct song *currentsong)
{
pid_t fd;
char *c_addr;
char *p;
int len;
char my_song[30]="/mp3/song/";
while(currentsong)
{
/*创建子进程,即孙子进程*/
fd = fork();
if(fd == -1)
{
perror("fork");
exit(1);
}
else if(fd == 0)
{
//--------------------------------------------------------
printf("child2 PID:%d\n", getpid()); //子进程ID
//--------------------------------------------------------
/*把歌曲名加上根路径*/
strcat(my_song,currentsong->songname);
p = my_song;
len = strlen(p);
/*去掉文件名最后的'\n'*/
my_song[len-1]='\0';
printf("THIS SONG IS %s\n",my_song);
execl("/mp3/madplay","madplay",my_song,NULL);
printf("\n\n\n");
//----------------------------------------------------
printf("execl(/mp3/madplay madplay)\n");
}
else
{
//------------------------------------------------------------
printf("parent2 PID:%d\n", getpid()); //父进程ID
//------------------------------------------------------------
/*内存映射*/
c_addr = shmat(shmid,0,0);
//fd = 55;
/*把孙子进程的id和当前播放歌曲的节点指针传入共享内存*/
memcpy(c_addr,&fd,sizeof(pid_t)); //孙子进程的ID号拷贝到共享内存
memcpy(c_addr + sizeof(pid_t)+1,¤tsong,4);
/*使用wait阻塞子进程,直到子进程播放完才能被唤醒;
当被唤醒时,表示播放MP3期间没有按键按下,则继续顺序播放下一首MP3*/
if(fd == wait(NULL))
{
currentsong = currentsong->next;
printf("THE NEXT SONG IS %s\n",currentsong->songname);
}
//----------------------------------------------------
printf("if(fd == wait(NULL))\n");
}
}
}
#endif
/*************************************************
Function name: creat_song_list
Parameter : void
Description : 创建歌曲名的双向循环链表
Return : struct song *
Argument : void
Autor & date : ada 09.12.07
**************************************************/
//
// p2 p1
// ----- -----
// | | | |
// |fwd--|---->|fwd |
// |-----| |-----|
// | | | |
// | bwd|<----|--bwd|
// |-----| |-----|
// | | | |
// |value| |value|
// |-----| |-----|
struct song *creat_song_list(void)
{
FILE *fd;
size_t size;
size_t len;
char *line = NULL;
struct song *head;
struct song *p1;
struct song *p2;
system("ls /mp3/song >song_list");
fd = fopen("song_list","r");
p1 = (struct song *)malloc(sizeof(struct song));
printf("==================================song list=====================================\n");
system("ls /mp3/song");
printf("\n");
printf("================================================================================\n");
//ssize_t getline(char **lineptr, size_t *n, FILE *stream)
size = getline(&line,&len,fd);
#if 0
printf("size = %d\n",size); //读取成功返回读取的字节数,失败返回-1
printf("line = %s\n",line); //存放第一行的首地址
printf("len = %d\n",len); //每一行分配的字节数
size_t length = strlen(line);
printf("length = %d\n",length);
printf("----------------------------\n")
#endif
//char *strncpy(char *dest, const char *src, size_t n);
strncpy(p1->songname,line,strlen(line));
head = p1;
while((size = getline(&line,&len,fd)) != -1)
{
p2 = p1; //p2表示上一个结点
p1 = (struct song *)malloc(sizeof(struct song)); //p1表示当前结点
//------------------------------------------
printf("p1 = %d\n",p1);
strncpy(p1->songname,line,strlen(line));
//------------------------------------------
printf("p1->songname = %s\n",p1->songname);
p2->next = p1; //p2--->p1
p1->prev = p2; //p2<---p1
//-----------------------------------------------
printf("size = %d\n",size); //读取的字节数
printf("line = %s\n",line); //存放第一行的首地址
printf("len = %d\n",len); //每一行分配的字节数
size_t length = strlen(line);
printf("length = %d\n",length);
printf("----------------------------\n");
}
p1->next = head; //尾结点指向首结点
head->prev = p1; //
p1 = NULL;
p2 = NULL;
system("rm -rf /mp3/song/song_list");
return head;
}
/*************************************************
Function name: startplay
Parameter : pid_t *,struct song *
Description : 开始播放函数
Return : void
Argument : void
Autor & date : ada 09.12.07
**************************************************/
void startplay(pid_t *childpid,struct song *my_song)
{
pid_t pid;
int ret;
/*创建子进程*/
pid = fork();
if(pid > 0)
{
//------------------------------------------------------
printf("parent1 PID:%d\n", getpid()); //父进程ID
//------------------------------------------------------
printf("pid PID:%d\n", pid); //进程ID
//------------------------------------------------------
*childpid = pid;
play_flag = 1;
//sleep(1);
/*把孙子进程的pid号传给父进程*/
memcpy(&gradchild,p_addr,sizeof(pid_t));
printf("gradchild = %d\n",gradchild); //孙子进程的ID号
}
else if(0 == pid)
{
//------------------------------------------------------
printf("child1 PID:%d\n", getpid()); //子进程ID
//------------------------------------------------------
/*子进程播放MP3函数*/
play(my_song);
}
}
/*************************************************
Function name: my_pause
Parameter : pid_t
Description : 暂停函数
Return : void
Argument : void
Autor & date : ada 09,12,07
**************************************************/
void my_pause(pid_t pid)
{
printf("=======================PAUSE!PRESS K1 TO CONTINUE===================\n");
kill(pid,SIGSTOP); //对孙子进程发送SKGSTOP信号
play_flag = 0;
}
/*************************************************
Function name: my_pause
Parameter : pid_t
Description : 停止播放函数
Return : void
Argument : void
Autor & date : ada 09,12,07
**************************************************/
void my_stop(pid_t g_pid)
{
printf("=======================STOP!PRESS K1 TO START PLAY===================\n");
kill(g_pid,SIGKILL); //对孙子进程发送SKGKILL信号
kill(pid,SIGKILL); //对子进程发送SKGKILL信号
first_key=1;
}
/*************************************************
Function name: conti_play
Parameter : pid_t
Description : 继续函数
Return : void
Argument : void
Autor & date : ada 09,12,07
**************************************************/
void conti_play(pid_t pid)
{
printf("===============================CONTINUE=============================\n");
kill(pid,SIGCONT); //对孙子进程发送SIGCONT信号
play_flag=1;
}
/*************************************************
Function name: next
Parameter : pid_t
Description : 下一首函数
Return : void
Argument : void
Autor & date : ada 09.12.07
**************************************************/
void next(pid_t next_pid)
{
struct song *nextsong;
printf("===============================NEXT MP3=============================\n");
/*从共享内存获得孙子进程播放歌曲的节点指针*/
memcpy(&nextsong,p_addr + sizeof(pid_t)+1,4);
/*指向下首歌曲的节点*/
nextsong = nextsong->next;
/*杀死当前歌曲播放的子进程,孙子进程*/
kill(pid,SIGKILL);
kill(next_pid,SIGKILL);
wait(NULL);
startplay(&pid,nextsong);
}
/*************************************************
Function name: prev
Parameter : pid_t
Description : 上一首函数
Return : void
Argument : void
Autor & date : yuanhui 09.12.08
**************************************************/
void prev(pid_t prev_pid)
{
struct song *prevsong;
/*从共享内存获得孙子进程播放歌曲的节点指针*/
printf("===============================PRIOR MP3=============================\n");
memcpy(&prevsong,p_addr + sizeof(pid_t)+1,4);
/*指向上首歌曲的节点*/
prevsong = prevsong->prev;
/*杀死当前歌曲播放的子进程,孙子进程*/
kill(pid,SIGKILL);
kill(prev_pid,SIGKILL);
wait(NULL);
startplay(&pid,prevsong);
}
文章评论(0条评论)
登录后参与讨论