您的位置:首页 > 财经 > 产业 > 管理软件开发平台_龙岩市人民政府官网_深圳网络络推广培训_推广平台排名前十名

管理软件开发平台_龙岩市人民政府官网_深圳网络络推广培训_推广平台排名前十名

2024/12/23 11:41:32 来源:https://blog.csdn.net/soi55gshig/article/details/142633040  浏览:    关键词:管理软件开发平台_龙岩市人民政府官网_深圳网络络推广培训_推广平台排名前十名
管理软件开发平台_龙岩市人民政府官网_深圳网络络推广培训_推广平台排名前十名

1.文件描述符的分配规则

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{int fd = open("myfile", O_RDONLY);if(fd < 0){perror("open");return 1;}printf("fd: %d\n", fd);close(fd);return 0;
}

当我们打开一个文件,他的fd是3,因为0 1 2 已经被占用了,当我们关闭0 和 1 ,再看这段代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{close(0);//close(2);int fd = open("myfile", O_RDONLY);if(fd < 0){perror("open");return 1;}printf("fd: %d\n", fd);close(fd);return 0;
}

会发现fd是0或者2 ,可见文件描述符的分配规则是找到当前没有被使用的最小的一个下标,作为新的文件描述符,

2.重定向的本质

如果我们关闭文件描述符 1 ,看代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main()
{close(1);int fd = open("myfile", O_WRONLY|O_CREAT, 00644);if(fd < 0){perror("open");return 1;}printf("fd: %d\n", fd);fflush(stdout);close(fd);exit(0);
}

会发现,本来应该打印到显示器上的内容,打印到文件"myfile"里面了,这是因为我们关闭了文件描述符1,然后打开一个文件,myfile的文件描述符就是1,所以,printf默认是向stdout输出的,但是stdout指向的文件描述符是1,所以就打印到myfile文件中了,这种现象叫做重定向输出

重定向的本质是什么呢?

3.dup2系统调用

#include <unistd.h>
int dup2(int oldfd, int newfd);

dup2是一个用于复制文件描述符的系统调用函数,,可以将一个文件描述符引用复制到另一个文件描述符中,这通常用于改变标准输入输出流的指向

示例代码

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main() {int fd = open("myfile", O_CREAT | O_RDWR);if (fd < 0) {perror("open");return 1;}close(1);dup2(fd, 1);for (;;) {char buf[1024] = {0};ssize_t read_size = read(0, buf, sizeof(buf) - 1);if (read_size < 0) {perror("read");break;}printf("%s", buf);fflush(stdout);}return 0;
}

ssize_t read_size = read(0, buf, sizeof(buf) - 1);

这段代码就是从标准输入读取数据,然后printf输出到文件标识符为1的文件中,也就是myfile中,

4.缓冲区的理解

缓冲区就是一段内存空间,为了给上层提供高效的IO体验,间接提高整体的效率,缓冲区有用户级缓冲区和内核级缓冲区,

缓冲区的刷新策略

1.立即刷新,fflush(stdout)

2.行刷新,显示器

3.全刷新,缓冲区写满才刷新,普通文件

4.特殊情况,进程退出,系统会自动刷新

5.在shell中加入重定向

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<errno.h>
#include<ctype.h>
#include<sys/stat.h>
#include<fcntl.h>#define SIZE 512
#define ZERO '\0'
#define SEP " "
#define NUM 32 
//宏函数
#define SkipPath(cwd) do{ cwd+=(strlen(cwd)-1);while(*cwd!='/')cwd-- ;}while(0)
#define SkipSpace(cmd,pos) do{while(1){if(isspace(cmd[pos]))pos++;else break;}}while(0)//重定向定义
#define None_Redir 0
#define In_Redir   1
#define Out_Redir  2
#define App_Redir  3int redir_type=None_Redir;
char*filename=NULL; char cwd[SIZE*2];
char* gArgv[NUM];
int lastcode=0;void Die()
{exit(1);
}const char* GetHome()
{const char*home=getenv("HOME");if(home==NULL)return "/";return home;
}const char* GetUserName()
{const char* name=getenv("USER");//从环境变量中获取USER路径if(name==NULL)return "None";return name;
}const char* GetHostName()
{const char* name=getenv("HOSTNAME");//从环境变量中获取HOSTNAME路径if(name==NULL)return "None";return name;
}const char* GetCwd()
{const char* cwd=getenv("PWD");//从环境变量中获取PWD路径if(cwd==NULL)return "None";return cwd;
}void MakeCommandLineAndPrint()
{char line[SIZE];const char* username=GetUserName();const char* hostname=GetHostName();const char* cwd=GetCwd();SkipPath(cwd);//分割路径,只需要最后面的一个路径//将用户名,主机名,路径都写入line中,cwd+1的原因是snprintf(line,sizeof(line),"[%s@%s %s]> ",username,hostname,strlen(cwd)==1?"/":cwd+1);printf("%s",line);fflush(stdout);
}int GetUserCommand(char command[],size_t n)
{char* s=fgets(command,n,stdin);if(s==NULL)return -1;command[strlen(command)-1]=ZERO;return strlen(command);
}void CheckRedir(char cmd[])
{// >  >>  <// "ls -a -l -n >  myfile.txt"int pos=0;int end=strlen(cmd);while(pos<end){if(cmd[pos]=='>'){if(cmd[pos+1]=='>'){cmd[pos++]=0;pos++;redir_type=App_Redir; SkipSpace(cmd,pos);filename=cmd+pos;}else {cmd[pos++]=0;redir_type=Out_Redir;SkipSpace(cmd,pos);filename=cmd+pos;}}else if(cmd[pos]=='<'){cmd[pos++]=0;redir_type=In_Redir;SkipSpace(cmd,pos);filename=cmd+pos;}else {pos++;}}
}void SplitCommand(char command[],size_t n)
{(void)n;//"ls -a -l -n"-> "ls" "-a" "-l" "-n"gArgv[0]=strtok(command,SEP);int index=1;while((gArgv[index++]=strtok(NULL,SEP)));}void Cd()
{const char*path=gArgv[1];if(path==NULL)path=GetHome();chdir(path); //改变当前工作路径char temp[SIZE*2];getcwd(temp,sizeof(temp));//获取当前工作路径snprintf(cwd,sizeof(cwd),"PWD=%s",temp);putenv(cwd);}int CheckBuildin()
{int yes=0;const char* enter_cmd=gArgv[0];if(strcmp(enter_cmd,"cd")==0){yes=1;Cd();}else if(strcmp(enter_cmd,"echo")==0&&strcmp(gArgv[1],"$?")==0){yes=1;printf("%d\n",lastcode);lastcode=0;}return yes; 
}void ExecuteCommand()
{pid_t id=fork();if(id<0)Die();else if(id==0){//重定向设置if(filename!=NULL){if(redir_type==In_Redir){int fd=open(filename,O_RDONLY);dup2(fd,0);}else if(redir_type==Out_Redir){int fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);dup2(fd,1);}else if(redir_type==App_Redir){int fd=open(filename,O_WRONLY|O_CREAT|O_APPEND,0666);dup2(fd,1);}else {}}//childexecvp(gArgv[0],gArgv);exit(errno);}else {//fatherint status=0;pid_t rid=waitpid(id,&status,0);if(rid>0){lastcode=WEXITSTATUS(status);if(lastcode!=0)printf("%s:%s:%d\n",gArgv[0],strerror(lastcode),lastcode);}}
}int main()
{int quit=0;while(!quit){redir_type=None_Redir;//1.输出命令行MakeCommandLineAndPrint();//2.获取用户命令字符串char usercommand[SIZE];int n=GetUserCommand(usercommand,sizeof(usercommand));if(n<=0)return 1;//2.1  checkredirCheckRedir(usercommand);//3.命令行字符串分割SplitCommand(usercommand,sizeof(usercommand));//4.检测命令是否是内建命令n=CheckBuildin();if(n) continue;//5.执行命令ExecuteCommand();}return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com