2016-08-27 17:37:44 db199410 阅读数 577
  • Linux驱动之USB设备驱动

    不管是USB设备还是USB接口,都会被注册到同一个bus上,也就是usb_bus_type,其之间的区别会在match函数中区分,之后再去绑定不同的driver。 当一个USB设备被插入的时候,USB设备驱动,也就是usb_generic_driver会跟USB设备交互,得到其所有的各种描述符,并为每个接口都定义成为一个device,之后再加载到usb_bus上,让其去匹配其对应的接口驱动程序。

    2562 人正在学习 去看看 韦东山

一、文件描述符简介
文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。习惯上,标准输入的文件描述符是 0,标准输出是 1,标准错误是 2。
画图表示
这里写图片描述

二、如何创建文件描述符
进程获取文件描述符最常见的方法是通过本机子例程open或create获取或者通过从父进程继承。fork创建出来的子进程会继承父进程的文件描述符表

三、文件描述符和文件指针的区别
文件描述符:在linux系统中打开文件就会获得文件描述符,它是个很小的正整数。每个进程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针。文件指针:C语言中使用文件指针做为I/O的句柄。文件指针指向进程用户区中的一个被称为FILE结构的数据结构。FILE结构包括一个缓冲区和一个文件描述符。所以两者之间是层级关系。

四、文件描述符的分配原则
最小的未被使用的文件描述符给刚打开的文件。
例子:将2号文件描述符close掉,打开一个文件,那么此时该文件的文件描述符就是1。下面我们来验证一下。

close(1);
    const char*buff="hello world";
    int fd=open("1.log",O_CREAT|O_WRONLY,0664);
    if(fd<0)
    {
        printf("open error\n");
        return 0;
    }
    printf("%s",buff);

输出:
这里写图片描述
这里写图片描述
可见printf()并没有输出到屏幕上,而是输出到了文件中去。
解释一下:printf原先是输出到标准输出流中去的,而此时fd此时为1,是文件1.log的文件描述符。即标准输出流的位置被换成了文件1.log,所以printf输出到了文件中去

2017-01-05 23:01:05 u013796074 阅读数 90
  • Linux驱动之USB设备驱动

    不管是USB设备还是USB接口,都会被注册到同一个bus上,也就是usb_bus_type,其之间的区别会在match函数中区分,之后再去绑定不同的driver。 当一个USB设备被插入的时候,USB设备驱动,也就是usb_generic_driver会跟USB设备交互,得到其所有的各种描述符,并为每个接口都定义成为一个device,之后再加载到usb_bus上,让其去匹配其对应的接口驱动程序。

    2562 人正在学习 去看看 韦东山

当某个程序打开文件时,操作系统返回相应的文件描述符,程序为了处理该文件必须引用此描述符。所谓的文件描述符是一个低级的正整数。最前面的三个文件描述符(012)分别与标准输入(stdin),标准输出(stdout)和标准错误(stderr)对应。因此,函数 scanf() 使用 stdin,而函数 printf() 使用 stdout。你可以用不同的文件描述符改写默认的设置并重定向进程的 I/O 到不同的文件。

1
、首先说什么是文件描述符,它有什么作用?
文件描述符是一个简单的整数,用以标明每一个被进程所打开的文件和socket。第一个打开的文件是0,第二个是1,依此类推。Unix 操作系统通常给每个进程能打开的文件数量强加一个限制。更甚的是,unix 通常有一个系统级的限制。
因为squid 的工作方式,文件描述符的限制可能会极大的影响性能。当squid 用完所有的文件描述符后,它不能接收用户新的连接。也就是说,用完文件描述符导致拒绝服务。直到一部分当前请求完成,相应的文件和socket 被关闭,squid 不能接收新请求。当squid发现文件描述符短缺时,它会发布警告。
在运行./configure 之前,检查你的系统的文件描述符限制是否合适,能给你避免一些麻烦。大多数情况下,1024 个文件描述符足够了。非常忙的cache可能需要4096或更多

    基于文件描述符的输入输出函数:
  open
:打开一个文件,并指定访问该文件的方式,调用成功后返回一个文件描述符。
  creat
:打开一个文件,如果该文件不存在,则创建它,调用成功后返回一个文件描述符。
  close
:关闭文件,进程对文件所加的锁全都被释放。
  read
:从文件描述符对应的文件中读取数据,调用成功后返回读出的字节数。
  write
:向文件描述符对应的文件中写入数据,调用成功后返回写入的字节数。
  ftruncate
:把文件描述符对应的文件缩短到指定的长度,调用成功后返回0
  lseek
:在文件描述符对应的文件里把文件指针设定到指定的位置,调用成功后返回新指针的位置。
  fsync:
将所有已写入文件中的数据真正写到磁盘或其他下层设备上,调用成功后返回0
  fstat
:返回文件描述符对应的文件的相关信息,把结果保存在struct stat中,调用成功后返回0
  fchown
:改变与打开文件相关联的所有者和所有组,调用成功后返回0
  fchmod
:把文件描述符对应的文件的权限位改为指定的八进制模式,调用成功后返回0
  flock
:用于向文件描述符对应的文件施加建议性锁,调用成功后返回0
  fcntl
:既能施加建议性锁也能施加强制性锁,能建立记录锁、读取锁和写入锁,调用成功后返回0
  dup
:复制文件描述符,返回没使用的文件描述符中最小的编号。
  dup2
:由用户指定返回的文件描述符的值,用来重新打开或重定向一个文件描述符。
  select
:同时从多个文件描述符读取数据或向多个文件描述符写入数据

2017-05-09 22:28:47 Exziro 阅读数 1245
  • Linux驱动之USB设备驱动

    不管是USB设备还是USB接口,都会被注册到同一个bus上,也就是usb_bus_type,其之间的区别会在match函数中区分,之后再去绑定不同的driver。 当一个USB设备被插入的时候,USB设备驱动,也就是usb_generic_driver会跟USB设备交互,得到其所有的各种描述符,并为每个接口都定义成为一个device,之后再加载到usb_bus上,让其去匹配其对应的接口驱动程序。

    2562 人正在学习 去看看 韦东山

文件描述符

  我们知道在Linux系统中一切皆文件,文件的类型也是多种多样的,有普通文件,目录文件,链接文件。而当系统需要调用文件时,又是如何进行操作的,而文件描述符就是因此而诞生的,文件描述符(file descriptor)是内核为了高效管理已被打开的文件创建的索引。文件描述符的操作返回的是一个文件描述符,内核会在每个进程空间中维护一个文件描述表,所有打开的文件都将通过此表中的文件描述符来引用。
  这里写图片描述
  fd通常是一个非负整数。用于指代被打开的文件,可以将其想象成为一个数组,fd则是数组的下标,而数组中的内容则是所代表的文件索引。所有执行I/O操作的系统调用都通过文件描述符。程序刚刚启动的时候,我们查看文件描述符会发现其返回值是3,这是因为程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。文件描述符0理解为我和计算机交互时的输入,而这个输入默认是指向键盘的; 文件描述符1理解为我和计算机交互时的输出,而这个输出默认是指向显示器的; 文件描述符2理解为我和计算机交互时,计算机出现错误时的输出,而这个输出默认是和文件描述符1指向一个位置;如果此时去打开一个新的文件,它的文件描述符会是3.POSIX标准要求每次打开文件时必须使用当前进程中最小可用的文件描述号码,因此,在网络通信过程中稍不注意就有可能造成串话,我们的通道就是利用其来进行操作的。

文件描述符与FILE结构

  fd只是一个整数,在open时产生。起到一个索引的作用,进程通过PCB中的文件描述符表找到该fd所指向的文件指针filp。文件描述符的操作(如: open)返回的是一个文件描述符,内核会在每个进程空间中维护一个文件描述符表, 所有打开的文件都将通过此表中的文件描述符来引用;
而流(如: fopen)返回的是一个FILE结构指针, FILE结构是包含有文件描述符的,FILE结构函数可以看作是对fd直接操作的系统调用的封装, 它的优点是带有I/O缓存

FILE结构体详解

  文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,struct file的指针通常被命名为file或filp。我们可以在系统文件中找到其完整的结构体定义。
  file 结构如下所示:
  struct file {
  union {
  struct list_head fu_list; 文件对象链表指针linux/include/linux/list.h
  struct rcu_head fu_rcuhead; RCU(Read-Copy Update)是Linux 2.6内核中新的锁机制
  } f_u;
  struct path f_path; 包含dentry和mnt两个成员,用于确定文件路径
  #define f_dentry f_path.dentry f_path的成员之一,当前文件的dentry结构
  #define f_vfsmnt f_path.mnt 表示当前文件所在文件系统的挂载根目录
  const struct file_operations *f_op; 与该文件相关联的操作函数
  atomic_t f_count; 文件的引用计数(有多少进程打开该文件)
  unsigned int f_flags; 对应于open时指定的flag
  mode_t f_mode; 读写模式:open的mod_t mode参数
  off_t f_pos; 该文件在当前进程中的文件偏移量
  struct fown_struct f_owner; 该结构的作用是通过信号进行I/O时间通知的数据。
  unsigned int f_uid, f_gid; 文件所有者id,所有者组id
  struct file_ra_state f_ra; 在linux/include/linux/fs.h中定义,文件预读相关
  unsigned long f_version;
  #ifdef CONFIG_SECURITY
  void *f_security;
  #endif
  
  void *private_data;
  #ifdef CONFIG_EPOLL
  
  struct list_head f_ep_links;
  spinlock_t f_ep_lock;
  #endif
  struct address_space *f_mapping;
  };
  在其中,有一些结构体是其中一些需要我们注意的例如:
  1.mode_t f_mode;
文件模式确定文件是可读的或者是可写的(或者都是), 通过位 FMODE_READ 和FMODE_WRITE. 你可能想在你的 open 或者 ioctl 函数中检查这个成员的读写许可, 但是不需要检查读写许可, 因为内核在调用你的方法之前检查. 当文件还没有为那种存取而打开时读或写的企图被拒绝, 驱动甚至不知道这个情况.
2.loff_t f_pos;
当前读写位置. loff_t 在所有平台都是 64 位( 在 gcc 术语里是 long long ). 驱动可以读这个值,如果它需要知道文件中的当前位置, 但是正常地不应该改变它; 读和写应当使用它们作为最后参数而收到的指针来更新一个位置, 代替直接作用于 filp->f_pos. 这个规则的一个例外是在 llseek 方法中, 它的目的就是改变文件位置.
3.unsigned int f_flags;
这些是文件标志, 例如 O_RDONLY, O_NONBLOCK, 和 O_SYNC. 驱动应当检查O_NONBLOCK 标志来看是否是请求非阻塞操作; 其他标志很少使用. 特别地, 应当检查读/写许可, 使用 f_mode 而不是f_flags. 所有的标志在头文件

2019-06-01 16:28:02 u011285208 阅读数 312
  • Linux驱动之USB设备驱动

    不管是USB设备还是USB接口,都会被注册到同一个bus上,也就是usb_bus_type,其之间的区别会在match函数中区分,之后再去绑定不同的driver。 当一个USB设备被插入的时候,USB设备驱动,也就是usb_generic_driver会跟USB设备交互,得到其所有的各种描述符,并为每个接口都定义成为一个device,之后再加载到usb_bus上,让其去匹配其对应的接口驱动程序。

    2562 人正在学习 去看看 韦东山

 文件描述符可以通过open等函数获得;

文件流可以通过fopen获取,然后通过fileno获取文件流对应的文件描述符。

#include "apue.h"

int
main(void)
{
	char	name[L_tmpnam], line[MAXLINE];
	FILE	*fp;
    struct stat             statbuf;
    char buf[1024] = {'\0'};
    char file_path[1000] = {'0'};   

	printf("%s\n", tmpnam(NULL));		/* first temp name */

	tmpnam(name);						/* second temp name */
	printf("%s\n", name);

	if ((fp = tmpfile()) == NULL)		/* create temp file */
		err_sys("tmpfile error");
	fputs("one line of output\n", fp);	/* write to temp file */
	rewind(fp);							/* then read it back */
	if (fgets(line, sizeof(line), fp) == NULL)
            err_sys("fgets error");
    fputs(line, stdout);				/* print the line we wrote */
    int fd = fileno(fp);
    printf("%d\n", fd);
    fstat(fd, &statbuf);

    /*这里进行文件路径的获取*/
    snprintf(buf, sizeof (buf), "/proc/self/fd/%d", fd);
    if (readlink(buf, file_path, sizeof(file_path) - 1) != -1) {
            printf("%s\n", file_path);
    }

    printf("asdf\n");
    sleep(200);

	exit(0);
}
[root@localhost stdio]# ./tempfiles
/tmp/fileZzCLWA
/tmp/filez3qU8z
one line of output
3
/tmp/tmpf5F52kz (deleted)
asdf
^C

 

2019-07-12 11:18:23 zhuawalibai 阅读数 152
  • Linux驱动之USB设备驱动

    不管是USB设备还是USB接口,都会被注册到同一个bus上,也就是usb_bus_type,其之间的区别会在match函数中区分,之后再去绑定不同的driver。 当一个USB设备被插入的时候,USB设备驱动,也就是usb_generic_driver会跟USB设备交互,得到其所有的各种描述符,并为每个接口都定义成为一个device,之后再加载到usb_bus上,让其去匹配其对应的接口驱动程序。

    2562 人正在学习 去看看 韦东山

一、查看当前系统使用的打开文件描述符数,可以使用下面的命令:

1

2

[root@localhost ~]# cat /proc/sys/fs/file-nr

1632 0 1513506

其中第一个数表示当前系统已分配使用的打开文件描述符数,第二个数为分配后已释放的(目前已不再使用),第三个数等于file-max。

二、进程最多打开的fd

查看:ulimit -n

临时设置:ulimit -n 1000000

 

没什么好说的,直接上代码

博文 来自: u011569364
没有更多推荐了,返回首页