没有选择双面打印,还出来双面打印提示,每次复印还都出来一张白纸,怎么回事? 求迅速解答2天内要,谢谢
563
2022-05-29
昨天完成的任务: Mplayer播放器安装成功,并且实现基本使用。
任务1: 学习linux下进程编程
1. 进程简介
进程是操作系统调度的最小单元,线程是进程内部的执行单元,一个进程默认有一个主线程。
进程在操作系统里使用PID号作为标识符号----查看当前终端运行的进程: ps 。
每个进程之间的资源都是独立的。--------进程可以自己独立的运行、带main----------
今天学习的主要任务:
1. 进程间通信: 管道(无名管道、命名管道)、消息队列、共享内存、内存映射(mmap)、信号。
2. execl函数族: 用于启动一个新的进程,新的进程开始执行之后,会覆盖原来进程空间。
3. dup2函数: 复制文件表。------实现文件描述符重定向。 dup2(fds[1],1);
4. 编写广告机播放器程序
5. 编写shell脚本,实现文件同步
1.1 进程创建
#include
pid_t fork(void);
功能: 在当前进程里再创建一个子进程。
函数返回值: ==0 表示子进程,>0表示父进程,<0表示出现错误
新创建的子进程特性: 在fork成功那一刻,会将父进程所有的资源全部拷贝一份,重新运行。
僵尸进程: 子进程先退出,父进程没有清理子进程的空间。如何清理子进程空间? wait();
孤儿进程: 父进程比子进程先退出。避免,就是父进程要保证最后退出。
1.2 等待子进程退出,并且清理子进程空间
#include
#include
pid_t wait(int *status);
函数功能: 随机等待一个子进程退出,并清理子进程资源。
返回值: 返回退出的子进程PID号。
函数的形参: int *status可以保存进程退出的状态。 exit(-1); //结束当前进程。
pid_t waitpid(pid_t pid, int *status, int options);
函数: 可以指定特定的PID号。-1表示所有子进程。
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char **argv)
{
int pid;
/*创建子进程*/
pid=fork();
if(pid==0) //子进程
{
printf("子进程正常运行!....\n");
sleep(1);
/*结束当前进程*/
exit(0);
}
else if(pid>0) //父进程
{
int state=0; //保存子进程退出状态值
/*阻塞-等待子进程退出*/
wait(&state);
printf("父进程提示: 子进程已经安全退出! 子进程退出的状态=%d\n",state);
}
else
{
printf("进程创建错误!");
}
return 0;
}
1.3 终止当前进程
#include
void _exit(int status);
#include
void _Exit(int status);
#include
void exit(int status);
1.4 管道通信
管道: FIFO文件,特性: 先入先出。
1.4.1 无名管道: 有亲缘关系之间的进程才可以使用无名管道进程通信。
无名管道这个FIFO文件没有实体。
如果创建无名管道?
#include
int pipe(int pipefd[2]);
函数形参: 传入一个数组的首地址。
管道创建成功之后: [0]表示(FIFO)无名管道读端。 [1]表示(FIFO)无名管道写端。
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char **argv)
{
int pid;
int pipefd[2];
/*创建无名管道*/
pipe(pipefd);
/*创建子进程*/
pid=fork();
if(pid==0) //子进程
{
printf("子进程正常运行!....\n");
sleep(1);
char *p="1234567";
write(pipefd[1],p,strlen(p)+1); //向管道的写端写入数据
/*结束当前进程*/
exit(0);
}
else if(pid>0) //父进程
{
int state=0; //保存子进程退出状态值
char buff[100];
read(pipefd[0],buff,100); //从管道的读端读取数据
printf("父进程收到的数据=%s\n",buff);
/*阻塞-等待子进程退出*/
wait(&state);
printf("父进程提示: 子进程已经安全退出! 子进程退出的状态=%d\n",state);
}
else
{
printf("进程创建错误!");
}
return 0;
}
1.4.2 命名管道通信
命名管道可以在任何进程间通,因为命名管道是一个实体文件,在磁盘可用找到该FIFO文件。
如何在磁盘上创建管道文件:
#include
#include
int mkfifo(const char *pathname, mode_t mode);
管道文件不能在共享目录下创建。(挂载的目录)
1.5 dup2函数学习
#include
int dup2(int oldfd, int newfd);
示例: dup2(fds[1],1); //接下来对文件描述符1的操作都是相当于对管道fds[1]操作。
文件描述符在内核里对应的是一个文件结构体。
示例1:
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char **argv)
{
int pid;
int pipefd[2];
/*创建无名管道*/
pipe(pipefd);
/*创建子进程*/
pid=fork();
if(pid==0) //子进程
{
printf("子进程正常运行!....\n");
dup2(pipefd[1],1);
//pipefd[1]管道写端,1表示当前进程的标准输出
sleep(1);
printf("---1234567---\n");
/*结束当前进程*/
exit(0);
}
else if(pid>0) //父进程
{
int state=0; //保存子进程退出状态值
char buff[100];
read(pipefd[0],buff,100); //从管道的读端读取数据
printf("父进程收到的数据=%s\n",buff);
/*阻塞-等待子进程退出*/
wait(&state);
printf("父进程提示: 子进程已经安全退出! 子进程退出的状态=%d\n",state);
}
else
{
printf("进程创建错误!");
}
return 0;
}
示例2: 日志功能制作。
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char **argv)
{
/*1.创建存放日志的文件*/
int fd=open("/log.txt",O_RDWR|O_CREAT,S_IRUSR|S_IWUSR);
/*2. 重定向(将标准输出重定向到fd)*/
dup2(fd,1);
/*3. 向日志文件写入数据*/
printf("12345\n");
printf("abcd\n");
printf("日志文件测试!\n");
/*4. 关闭日志文件*/
close(fd);
return 0;
}
1.6 execl 函数族
#include
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[]);
execl功能介绍: 启动新的子进程,当子进程启动成功之后会覆盖原来的进程空间。
Execl函数族介绍:
1. 带p表示可执行文件可以从环境变量里获取。
2. 不带p表示,可执行文件需要填绝对路径。
3. 带e表示最后的参数,可以给新进程设置新的环境变量。
说明: 参数列表最后面都要加一个NULL。
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char **argv)
{
/*以ls命令为例子,讲解*/
//execl(<可执行程序的路径>,<执行的形参列表>,NULL);
//execl("/bin/ls","ls","-l",NULL);
//execlp("ls","ls","-l",NULL);
//char *envp[]={"PATH1=12345",NULL};
//execle("/bin/ls","ls","-l",NULL,envp);
//获取环境变量的值: getenv("PATH1");
//char *argvs[]={"ls","-l",NULL};
//execv("/bin/ls",argvs);
char *argvs[]={"ls","-l",NULL};
execvp("ls",argvs);
printf("执行失败!\n");
return 0;
}
//ls -l
1.7 mplayer播放器
Mplayer运行有两个模式: 1. 主模式 2.从模式
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
获取标准输入的数据、写给FIFO文件
*/
void *pthread_func(void *argv)
{
int fd=open("/mplayer_fifo",2);
if(fd<0)
{
printf("FIFO文件打开失败!\n");
pthread_exit(NULL); //结束当前线程
}
char buff[100];
int len;
while(1)
{
printf("请输入命令:");
fflush(stdin); //刷新缓冲区
fgets(buff,100,stdin); //从键盘上获取数据 get_percent_pos get_file_name
len=strlen(buff); // get_file_name [0~12] [13]='\n'
write(fd,buff,len); // get_file_name '\n'
memset(buff,0,100);
}
}
int main(int argc,char **argv)
{
int pid;
/*1. 创建无名管道*/
int fds[2];
pipe(fds);
/*2. 创建子进程*/
pid=fork();
/*子进程代码: mplayer播放器*/
if(pid==0)
{
/*将子进程的标准输出重定向到管道写端*/
dup2(fds[1],1);
/*启动子进程*/
execlp("mplayer","mplayer","-zoom","-x","800","-y","480","-slave","-quiet","-input","file=/mplayer_fifo","/work/video_file/Video_2018-12-11.wmv",NULL);
}
else /*父进程*/
{
char buff[100];
int cnt=0;
/*创建新的线程: 从键盘上获取输入的数据,写给播放器的FIFO文件*/
pthread_t threadID;
pthread_create(&threadID,NULL,pthread_func,NULL);
pthread_detach(threadID); //设置分离属性
while(1)
{
/*从管道的读端读取数据: 读取就是mplayer播放器输出的数据*/
cnt=read(fds[0],buff,100);
buff[cnt]='\0';
printf("播放器输出的值=%s\n",buff);
}
}
return 0;
}
任务2: 广告机项目
广告机项目要求:
广告机应用场景: 公交站台、地铁车厢、银行前台大厅、高速公路、公园….
1. 有些广告机只有视频播放,没有声音。
2. 广告机都支持网络视频文件更新---->文件更新使用现成的服务器: FTP服务器、NFS服务器。
(1) 如何判断服务器上那些文件需要下载到本地? 通过shell脚本代码或者使用C语言。
(2) 更新的时间一般是固定的: 20:00 23:00 …… 通过时间函数判断时间是否到达。
(3) 在视频文件更新的时候,视频需要停止播放,可以在屏幕上显示提示(正在更新…..)。
3. 广告机需要支持自动播放,播放一个自动切换下一个、循环播放。
调用读目录、循环遍历目录、得到视频文件、mplayer播放器需要使用子进程方式启动。
广告机: 音量调整、选择视频播放…….都不是广告机的功能---是视频播放器的功能。
#include
Linux 任务调度 视频
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。