IO和进线程系列主要总结IO和进程、线程的知识,本篇主要对嵌入式系列学习5:IO和进线程知识总结涉及到的学习内容进行实践练习,给出相应实践要求,通过知识学习,运用起来。其中包括运用标准IO实现查单词、文件IO实现加密图片、ls -l等Linux快捷命令、运用strtok函数自己实现bash的效果、通过多线程进行读写操作、进程间通信的方式实现本地聊天软件。
整篇是本人通过学习进行笔记记载,如有不足,还请不要吝啬指出。另外我们提供嵌入式项目毕设资料与服务,远程部署、代码讲解、全方位服务。我们有专门的毕设项目辅导群(QQ:596557438),我们还有很多相关项目资料汇总,快进来瞧瞧,总有你所需!!!
涉及到的知识总结篇:
项目源码资料下载地址:箫声商城
易学蔚来全套毕设演示(看上哪个选那个): 易学蔚来全套毕业设计汇总 · 语雀
毕设服务真实反馈,在线观看: 客户真实反馈 · 语雀
实践1:查单词
流程:
打开文件
循环
输入一个单词
遍历文件
打印出单词信息
重新开始查询
关闭文件
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE *fp =fopen("./dict.txt","r");
if(NULL == fp)
{
perror("fopen failed!\n");
return -1;
}
char let[32] = {0};
char str[100] = {0};
while(1)
{
printf("please input letter:");
fgets(let,sizeof(let),stdin);
if(let[0] == '\n' )
{
break;
}
int n = strlen(let);
rewind(fp);
while(1)
{
char *p = fgets(str,sizeof(str),fp);
if(NULL == p)
{
printf("fgets failed!\n");
break;
}
if(strncmp(let,str,n-1)==0)
{
printf("%s\n",str);
break;
}
memset(str,0,sizeof(str));
}
memset(let,0,sizeof(let));
}
fclose(fp);
return 0;
}
实践2:使用文件IO的函数加密图片 (音频、视频)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
if(argc!=2)
{
printf("%s picture\n", argv[0]);
return -1;
}
int fd = open(argv[1], O_RDWR);
if(fd < 0)
{
perror("open");
return -1;
}
char buf[10] ={0};
read(fd, buf, 10);
int i;
for(i=0; i<5; i++)
{
buf[i] ^= buf[9-i];
buf[9-i] ^= buf[i];
buf[i] ^= buf[9-i];
}
lseek(fd, 0 , SEEK_SET);
write(fd, buf, 10);
printf("加密解密成功!\n");
close(fd);
return 0;
}
实践3: 完成ls -l
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <time.h>
#include <sys/sysmacros.h>
#include <grp.h>
#include <dirent.h>
int main(int argc, const char *argv[])
{
if(argc!=2)
{
printf("%s 文件路径名\n", argv[0]);
return -1;
}
DIR *dirp = opendir(argv[1]);
if(dirp == NULL)
{
perror("opendir failed!\n");
return -1;
}
chdir(argv[1]); //改变工作目录
while(1)
{
struct dirent *p= readdir(dirp);
if( p == NULL )
{
break;
}
while(NULL != p)
{
if( strncmp(p->d_name, ".", 1) == 0 )
{
break;
}
struct stat mybuf;
stat(p->d_name, &mybuf);
//文件类型
if(S_ISREG(mybuf.st_mode))
{
printf("-");
}
else if(S_ISDIR(mybuf.st_mode))
{
printf("d");
}
else if(S_ISCHR(mybuf.st_mode))
{
printf("c");
}
else if(S_ISBLK(mybuf.st_mode))
{
printf("b");
}
else if(S_ISFIFO(mybuf.st_mode))
{
printf("p");
}
else if(S_ISLNK(mybuf.st_mode))
{
printf("l");
}
else if(S_ISSOCK(mybuf.st_mode))
{
printf("s");
}
//文件权限
printf("%c", (mybuf.st_mode & (0x1<<8) )?'r':'-');
printf("%c", (mybuf.st_mode & (0x1<<7) )?'w':'-');
printf("%c", (mybuf.st_mode & (0x1<<6) )?'x':'-');
printf("%c", (mybuf.st_mode & (0x1<<5) )?'r':'-');
printf("%c", (mybuf.st_mode & (0x1<<4) )?'w':'-');
printf("%c", (mybuf.st_mode & (0x1<<3) )?'x':'-');
printf("%c", (mybuf.st_mode & (0x1<<2) )?'r':'-');
printf("%c", (mybuf.st_mode & (0x1<<1) )?'w':'-');
printf("%c", (mybuf.st_mode & (0x1<<0) )?'x':'-');
//链接数
printf(" %-2ld ", mybuf.st_nlink);
//用户名
struct passwd *m = getpwuid(mybuf.st_uid);
printf(" %-5s ", m->pw_name);
//组名
struct group *q = getgrgid(mybuf.st_gid);
printf(" %-5s ", q->gr_name);
//文件大小
printf(" %-5ld ", mybuf.st_size);
//最后一次修改的时间
struct tm *k = localtime(&mybuf.st_mtime);
printf(" %-2d %-2d %-2d:%-2d ", k->tm_mon+1,k->tm_mday,k->tm_hour,k->tm_min);
//文件名
printf("%s\n ",p->d_name);
p = readdir(dirp);
}
}
closedir(dirp);
return 0;
}
实践4.1: myshell.c (自己实现 bash 的效果)
strtok();
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define N 64
int main(int argc, char *argv[])
{
char buf[N] = {0}; //定义并初始化一个字符串数组
char *arg[N]; //定义一个指针数组
pid_t pid;
int i = 0, j;
while (1)
{
printf("linux@ubuntu:~$");
fgets(buf, N, stdin);//ls -l -a //等待用户从键盘输入,回车后将输入的内容写到buf,包括 \n,
//此时,buf数组中以\0结尾,\0 前面是 \n,显然 \n 不是命令
buf[strlen(buf)-1] = '\0'; //将buf数组中的\0前面的那个\n用\0进行覆盖
if (strcmp(buf, "exit") == 0) //看输入的是否为exit,注:没有对空格进行处理
break;
if ((pid = fork()) == -1) //创建子进程
{
perror("fork");
exit(-1);
}
if (pid == 0)
{
/*
下面是利用strtok函数将buf数值进行解析,把命令和参数分别解析出来,strtok函数的使用参见
C语言函数大全:下面是部分内容
头文件:#include <string.h>
定义函数:char * strtok(char *s, const char *delim);
函数说明:strtok()用来将字符串分割成一个个片段. 参数s 指向欲分割的字符串, 参数delim 则为分割字符串,当strtok()在参数s 的字符串中发现到参数delim 的分割字符时则会将该字符改为\0 字符. 在第一次调用时,strtok()必需给予参数s 字符串, 往后的调用则将参数s 设置成NULL. 每次调用成功则返回下一个分割后的字符串指针.
返回值:返回下一个分割后的字符串指针, 如果已无从分割则返回NULL.
范例
#include <string.h>
#include <stdio.h>
int main(void)
{
char s[] = "ab-cd : ef;gh :i-jkl;mnop;qrs-tu: vwx-y;z";
char *delim = "-: ";
char *p;
printf("%s ", strtok(s, delim));
while((p = strtok(NULL, delim)))
printf("%s ", p);
printf("\n");
return 0;
}
执行结果:
ab cd ef;gh i jkl;mnop;qrs tu vwx y;z //-与:字符已经被\0 字符取代
*/
arg[i] = strtok(buf, " ");
do
{
++i;
arg[i] = strtok(NULL, " ");
}while(arg[i] != NULL);
for (j = 0; j < i; j++)
printf("%s\n", arg[j]);
// char * arg[] = {"ls", "-l", "-a", NULL};
if (-1 == execvp(arg[0], arg)) //在子进程中调用execvp函数,子进程的三段被替换
{
perror("execvp");
exit(-1);
}
}
else
wait(NULL); //父进程等待子进程就是,即等待argv[0]中指向的命令执行完
}
return 0;
}
实践4.2:copy.c (用多线程进行读写操作)
同步和互斥都可以
第一种:运用同步信息量
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
sem_t sem1,sem2;
char buf[100] = {0};
int flag = 0;
int n = 0;
void *read_data(void *arg)
{
//先读 从1.txt读取
int fd = open("./1.txt", O_RDONLY);
while(1)
{
sem_wait(&sem2); //灯B -1
n = read(fd, buf, sizeof(buf));
if(n < 0)
{
perror("read");
return NULL;
}
else if(n == 0)
{
flag = 1;
close(fd);
break;
}
sem_post(&sem1); //灯A +1
}
}
void *write_data(void *arg)
{
//再写到2.txt
int fd = open("./2.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
while(1)
{
sem_wait(&sem1); //灯A -1
write(fd, buf, n);
if(flag == 1)
{
close(fd);
break;
}
sem_post(&sem2); //灯B +1
}
}
int main(int argc, const char *argv[])
{
sem_init(&sem1, 0, 0); //灯A
sem_init(&sem2, 0, 1); //灯B
pthread_t tid1,tid2;
pthread_create(&tid1, NULL, read_data, NULL);
pthread_detach(tid1);
pthread_create(&tid2, NULL, write_data, NULL);
pthread_detach(tid2);
while(1);
return 0;
}
第二种:运用互斥锁
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
char buf[100] = {0};
int fd1,fd2,n=0;
pthread_mutex_t mutex; //互斥锁的变量
void *myread(void *arg)
{
fd1 = open( "./1.txt" , O_RDONLY);
while(1)
{
pthread_mutex_lock(&mutex);
n = read(fd1, buf, sizeof(buf));
sleep(1);
if(n== 0)
{
perror("read");
break;
}
pthread_mutex_unlock(&mutex);
}
}
void *mywirte(void *arg)
{
fd2 = open( "./2.txt" , O_WRONLY|O_CREAT|O_TRUNC, 0666);
while(1)
{
write(fd2,buf,n);
sleep(1);
}
}
int main(int argc, const char *argv[])
{
//初始化互斥锁
pthread_mutex_init(&mutex, NULL);
pthread_t tid1,tid2;
pthread_create(&tid1, NULL, myread, NULL);
pthread_detach(tid1);
pthread_create(&tid2, NULL, mywirte, NULL);
pthread_detach(tid2);
pthread_join(tid2,NULL);
while(1);
return 0;
}
实践5:实现本地聊天软件(管道)
user1:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
char buf[100] = {0};
void *write_data(void *arg)
{
int fd = open("./f1", O_WRONLY);
while(1)
{
fgets(buf,sizeof(buf),stdin);
write(fd, buf, strlen(buf));
}
}
void *read_data(void *arg)
{
int fd = open("./f2", O_RDONLY);
while(1)
{
read(fd, buf, sizeof(buf));
printf("buf=%s\n", buf);
memset(buf, 0, 100);
}
}
int main(int argc, char *argv[])
{
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,read_data,NULL);
pthread_detach(tid1);
pthread_create(&tid2,NULL,write_data,NULL);
pthread_detach(tid2);
while(1);
return 0;
}
user2:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
char buf[100] = {0};
void *write_data(void *arg)
{
int fd = open("./f2", O_WRONLY);
while(1)
{
fgets(buf,sizeof(buf),stdin);
write(fd, buf, strlen(buf));
}
}
void *read_data(void *arg)
{
int fd = open("./f1", O_RDONLY);
while(1)
{
read(fd, buf, sizeof(buf));
printf("buf=%s\n", buf);
memset(buf, 0, 100);
}
}
int main(int argc, char *argv[])
{
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,read_data,NULL);
pthread_detach(tid1);
pthread_create(&tid2,NULL,write_data,NULL);
pthread_detach(tid2);
while(1);
return 0;
}
持续更新中.......
更多文章,点击左上角头像,查看个人简介和更多相关项目的分享,也可通过关注我的其他平台,(嵌入式-箫声)一起学习,一起进步!Come on!!!动起手来,开始探索~~~