设备文件和IO

设备文件和IO

1.在Linux下面一切都看成是文件,包括设备、soket、管道等等。

命令:
stat 文件名      (查看文件的节点号)节点号:IO Block
mknod 文件名 c 5 0(让普通的文件和设备进行关联)c:字符设备 5:主设备号,5是屏幕终端的设备 0:次设备号,表示第一块屏幕。让文件和显示设备关联。

 

2.C语言API:通过C库函数实现,基于系统调用上实现的。
系统调用:通过软中断的方式向内核提供请求,从而获取内核函数的服务入口。让系统从用户空间进入内核空间运行,运行后将结果返回给应用程序。

           基于       基于  基于
bash---->Shell---->C---->系统调用

3.文件描述符(int类型)_fd
FILE指针里有个   文件描述符的东西(int类型) 

打开文件的过程:

程序运行的时候给每个进程分配一个PCB(就是task_strut(包含有files的指针))
files指针用来保存打开文件的列表files_struct{fd[0],fd[1],fd[2]……}文件列表里包含有文件描述符0,1,2……
(0-stdin,1-stdout,2-stderr)每个进程被加载后,默认打开0,1,2这三个文件描述符。
打开第一个文件文件描述符为3;再打开一个文件文件描述符为4……(连续递增,知道达到#ulimit –n的限制为止)。

fd[1]--->file { f_flags(打开文件的标识读、写)
  f_pos(文件打开的位置)
  f_owner
  f_count
  f_dentry(文件路径)-->struct dentry{d_inode(编号:作用是帮我们找到文件在硬盘的位置)}
       }

每个进程能够访问的文件描述符是有限制的,通过#ulimit –n可以查看和更改

以后操作文件都是通过文件描述符去操作。

open()打开系统调用
int open(const char *path, int flags);
path :文件的名称,可以包含(绝对和相对)路径
flags:文件打开模式
打开成功:返回文件描述符;
打开失败:返回-1

 

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
//***************************************课堂练习**********************************************
//****************2013.10.13.
//****************文件锁int fcntl(int fd, int cmd, struct flock *lock)
//***************************************课堂练习**********************************************
int main()
{
 struct flock lock;
 int fd = open("myfile1", O_RDWR | O_CREAT, S_IRWXU);
 if (fd < 0)               //打开失败返回-1,打开成功放回文件描述符
 {
  perror("文件打开失败!\n");
  exit(-1);
 }
 
 memset(&lock, 0, sizeof(lock));
 //读锁
 fcntl(fd, F_GETLK, &lock);
 //判断是否有锁
 if (lock.l_type != F_UNLCK)
 {
  printf("File is lock! exit...");
  exit(1);//有锁退出
 }
 //文件空锁状态,把锁设置成写锁
 lock.l_type = F_WRLCK;
 fcntl(fd, F_SETLK, &lock);
 printf("Set lock!\n");

 //延时5s来模拟文件锁起来了
 sleep(5);
 //把锁设置成空锁状态
 lock.l_type = F_UNLCK;
 fcntl(fd, F_SETLK, &lock);
 printf("Set unlock!\n");
 
 close(fd);
 return 0;
}

// struct flock
// {
//  short  l_type;                 /* 锁的类型 */
//  short  l_whence;           /* 偏移量的起始位置: */
//  off_t   l_start;                /* 从l_whence的偏移量 */
//  off_t   l_len;                  /* 从l_start开始的字节数 */
//  pid_t  l_pid;                  /* 锁所属进程ID(一般不用) */
// }
// l_type有F_RDLCK读锁、F_WRLCK写锁及F_UNLCK空锁。
// l_whence有SEEK_SET、SEEK_CUR和SEEK_END。
// l_len为0时表示从起点开始直至最大可能位置为止。

 

要求如下:
1、程序运行命令格式:
         serialchat [-options];
[options]: p-输出打印serial.cfg各个配置项信息,格式:参数-----参数值;
               s-进行菜单(有保存和退出)让用户设置;
            f-指定配配置项设置,输出各选项置文件名,并输出各配置项信息 
               其他选项提示该程序用法帮助。
2、不支持serialchat运行两次
3、如果无法找到配置文件,则提示运行失败,原因:配置文件无法找到

#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
typedef struct FILE_T
{
 char *pos;
 char *val;
}MYFILE;

bool readline(MYFILE *mfp, char *rslt);
char *ltrim(char *str);
int find(char *str, char ch);
int findstr(char *fstr, char *sstr);
void printmsg(char *str);

int main(int argc, char *argv[])
{
 if (argc < 2)
 {
  printf("p-输出打印serial.cfg各个配置项信息,格式:参数-----参数值;\n"
   "s-进行配置项设置,输出各选项菜单(有保存和退出)让用户设置;\n"
   "f-指定配置文件名,并输出各配置项信息\n");
  return 0;
 }
 if (strcmp(argv[1], "-p") != 0 &&
  strcmp(argv[1], "-s") != 0 &&
  strcmp(argv[1], "-f") != 0)
 {
  printf("p-输出打印serial.cfg各个配置项信息,格式:参数-----参数值;\n"
   "s-进行配置项设置,输出各选项菜单(有保存和退出)让用户设置;\n"
   "f-指定配置文件名,并输出各配置项信息\n");
  return 0;
 }
 int fd;
 
 struct flock lock; //文件锁
 const char *fname = "serial.cfg"; //默认的文件
 //-f选项
 if (strcmp(argv[1], "-f") == 0)
 {
  char othername[100];
  printf("输入配置文件名:");
  scanf("%s", othername);
  fname = othername; //默认的文件改文新的文件
 }
 if ((fd = open(fname, O_RDWR|O_EXCL)) == -1)
 {
  printf("没有该文件。\n");
  return 1;
 }

 //文件上锁
 memset(&lock, 0, sizeof(struct flock));
 if (fcntl(fd, F_GETLK, &lock) == 0)
 {
  if (lock.l_type != F_UNLCK)
  {
   printf("文件被占用,退出程序\n");
   close(fd);
   return 1;
  }
  lock.l_type = F_WRLCK;
  if (fcntl(fd, F_SETLK, &lock) != 0)
  {
   printf("锁住文件失败\n");
   close(fd);
   return 1;
  }


  char fval[4096] = {0};
  read(fd, fval, 4095); //读文件
  printmsg(fval);   //打印配置文件内容。去除空格,去注释


  if (strcmp(argv[1], "-s") == 0)
  {
   char key[20] = {0};
   int keypos;
   while (1)
   {
    printf("输入键名(key)(输入#exit退出):");
    scanf("%s", key);
    if (strcmp(key, "#exit") == 0)
    {
     break;
    }
    if ((keypos = findstr(fval, key)) != -1)
    {
     char val[20];
     char *tmp = fval+keypos;
     int pos = find(tmp, '=');
     if (pos == -1)
     {
      printf("错误重新输入!\n");
      continue;
     }
     printf("输入键值(val):");
     scanf("%s", val);      
     memcpy(tmp+pos+1, val, strlen(val)); 
     printmsg(fval);
     char buf[10];
     gets(buf);
     printf("是否保存?(y/n):");
     if (getchar() == 'y')
     {
      lseek(fd, 0, SEEK_SET);
      write(fd, fval, strlen(fval));
      printf("保存成功\n");
     }
    }
   }
  }
  lock.l_type = F_UNLCK;
  fcntl(fd, F_SETLK, &lock);
 }
 close(fd);
}

bool readline(MYFILE *mfp, char *rslt)
{
 char *p = mfp->pos;
 if (*p == '\0')
 {
  return false;
 }
 int i = 0;
 while (*p != '\0' && *p != '\n')
 {
  rslt[i++] = *p;
  p++;
 }
 rslt[i] = '\0';
 if (*p == '\n')
 {
  p++;
 }
 mfp->pos = p;
 return true;
}

char *ltrim(char *str)
{
 while (*str == ' ')
 {
  str++;
 }
 return str;
}

int find(char *str, char ch)
{
 int i = 0;
 while (str[i] != ch && i < strlen(str))
 {
  i++;
 }
 if (str[i] == 0)
 {
  return -1;
 }
 return i;
}

int findstr(char *fstr, char *sstr)
{
 int i = 0;
 while (1)
 {
  if (fstr[i] == 0)
  {
   return -1;
  }
  if (memcmp(fstr+i, sstr, strlen(sstr)) == 0)
  {
   return i;
  }
  i++;
 }
}
void printmsg(char *str)
{
 int pos = 0;
 int prev = 0;
 MYFILE ff;
 ff.pos = str;
 ff.val = str;
 
 char line[80];
 while (readline(&ff, line))
 {
  char *tline = ltrim(line);
  if (tline[0] == '#')
  {
   continue;
  }
  int pos;
  if ((pos = find(tline, '=')) == -1)
  {
   continue;
  }
  char key[20] = {0};
  memcpy(key, tline, pos);
  char val[20] = {0};
  memcpy(val, tline+pos+1, strlen(tline)-pos-1);
  printf("%s = %s\n", key, val);
 }
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值