热度 15
2012-7-5 19:43
2223 次阅读|
0 个评论
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 ; 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 ="/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 ='\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); }