2019-04-19 19:44:16 qq_37266079 阅读数 222

linux系统函数

1.Linux函数简述

  • Linux系统函数的用法必须结合Linux内核的工作原理 来理解,因为系统函数正是内核提供给应用程序的接口,而要理解内核的工作原理,必须熟练掌握C语言,因为内核也是用C语言写的。
  • 我们在描述内核工作原理时必然要用“指 针”、“结构体”、“链表”这些名词来组织语言,就像只有掌握了英语才能看懂英文书一样,只有学好了C语言才能看懂我描述的内核工作原理。

2.文件I/O

2.1-C标准库函数和系统函数的关系

2.2文件描述符

文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。

一个进程默认打开3个文件描述符:

STDIN_FILENO 0
STDOUT_FILENO 1
STDERR_FILENO 2

标准输入(STDIN_FILENO)的文件描述符是 0
标准输出(STDOUT_FILENO )的文件描述符是 1
标准错误(STDERR_FILENO )的文件描述符是 2。

  • 新打开文件返回文件描述符表中未使用最小文件描述符。
  • 文件描述符的有效范围是0OPEN_MAX。一般来说,每个进程最多可以打开64个文件(0 — 63)。

2.3-task_struct结构体

  • 为了管理进程,操作系统必须对每个进程所做的事情进行清楚的描述,为此,操作系统使用数据结构来代表处理不同的实体,这个数据结构就是通常所说的进程控制块PCB)。
  • linux操作系统下这就是task_struct结构体 ,所属的头文件#include <sched.h>每个进程都会被分配一个task_struct结构,它包含了这个进程的所有信息

这个进程的主要信息

  • 1、与进程相关的唯一标识符:区别正在执行的进程和其他进程

  • 2、状态:描述进程的状态,因为进程有阻塞、挂起、运行等好几个状态,所以都有个表示符来记录进程的执行状态。

  • 3、优先级:如果有好几个进程正在执行,就涉及到进程的执行的先后顺序,这和进程的优先级这个标识符有关。

  • 4、程序计数器:程序中即将被执行指令的下一条地址。

  • 5、内存指针:程序代码和进程相关数据的指针。

  • 6、上下文数据:进程执行时处理器的寄存器中的数据。

  • 7、I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。

  • 8、记账信息:包括处理机的时间总和,记账号等等

2.4-files_struct结构体

  • files_struct结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 files_struct
  • 它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,files_struct的指针通常被命名为filefilp

2.5-文件描述符、task_struct结构体(PBC)、files_struct结构体三者关系

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

    2.6-open函数
  • open函数有两种形式,一种带两个参数,一种带三个参数
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode); 
返回值:成功返回新分配的文件描述符,出错返回-1并设置errno

pathname参数是要打开或创建的文件名,和fopen一样,pathname既可以是相对路径也可以是绝对路径flags参数有一系列常数值可供选择,可以同时选择多个常数用按位或运算符连接起来,所以这些常数的宏定义都以O_开头,表示or

flag参数选项

必选项:以下三个常数中必须指定一个,且仅允许指定一个。

  • O_RDONLY 只读打开
  • O_WRONLY 只写打开
  • O_RDWR 可读可写打开

可选项:以下可选项可以同时指定0个或多个,和必选项按位或起来作为flags参数。可选项有很多, 这里只介绍一部分。

  • O_APPEND 表示追加。如果文件已有内容,这次打开文件所写的数据附加到文件的末尾 而不覆盖原来的内容。
  • O_CREAT 若此文件不存在则创建它。使用此选项时需要提供第三个参数mode,表示该 文件的访问权限。
  • O_EXCL 如果同时指定了O_CREAT,并且文件已存在,则出错返回。
  • O_TRUNC 如果文件已存在,并且以只写或可读可写方式打开,则将其长度截断(Trun- cate)为0字节。
  • O_NONBLOCK对于设备文件,以O_NONBLOCK方式打开可以做非阻塞I/O(Nonblock I/ O)

2.7-close函数
close函数关闭一个已打开的文件:

#include <unistd.h> int close(int fd);
返回值:成功返回0,出错返回-1并设置errno

参数fd是要关闭的文件描述符。需要说明的是,当一个进程终止时,内核对该进程所有尚未关闭的文件描述符调用close关闭,所以即使用户程序不调用close,在终止时内核也会 自动关闭它打开的所有文件。但是对于一个长年累月运行的程序(比如网络服务器),打开 的文件描述符一定要记得关闭,否则随着打开的文件越来越多,会占用大量文件描述符和系统资源。

参考文章:
https://www.cnblogs.com/pluslius/p/10088929.html
https://blog.csdn.net/daboluo521/article/details/79598281
https://www.cnblogs.com/hanxiaoyu/p/5677677.html

2018-11-06 18:12:36 hddghhfd 阅读数 229

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

1. 函数说明

pipe(建立管道):
1) 头文件 #include<unistd.h>
2) 定义函数: int pipe(int filedes[2]);
3) 函数说明: pipe()会建立管道,并将文件描述词由参数filedes数组返回。
              filedes[0]为管道里的读取端
              filedes[1]则为管道的写入端。
4) 返回值:  若成功则返回零,否则返回-1,错误原因存于errno中。

    错误代码:
         EMFILE 进程已用完文件描述词最大量
         ENFILE 系统已无文件描述词可用。
         EFAULT 参数 filedes 数组地址不合法。

2. 举例

#include <unistd.h>#include <stdio.h>int main( void ){    int filedes[2];    char buf[80];    pid_t pid;        pipe( filedes );    pid=fork();            if (pid > 0)    {        printf( "This is in the father process,here write a string to the pipe.\n" );        char s[] = "Hello world , this is write by pipe.\n";        write( filedes[1], s, sizeof(s) );        close( filedes[0] );        close( filedes[1] );    }    else if(pid == 0)    {        printf( "This is in the child process,here read a string from the pipe.\n" );        read( filedes[0], buf, sizeof(buf) );        printf( "%s\n", buf );        close( filedes[0] );        close( filedes[1] );    }        waitpid( pid, NULL, 0 );        return 0;}

运行结果:


[root@localhost src]# gcc pipe.c
[root@localhost src]# ./a.out
This is in the child process,here read a string from the pipe.
This is in the father process,here write a string to the pipe.
Hello world , this is write by pipe.

当管道中的数据被读取后,管道为空。一个随后的read()调用将默认的被阻塞,等待某些数据写入。

若需要设置为非阻塞,则可做如下设置:

        fcntl(filedes[0], F_SETFL, O_NONBLOCK);
        fcntl(filedes[1], F_SETFL, O_NONBLOCK);

 

           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述
2018-11-06 00:36:34 gdfjhc 阅读数 128

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

execlp
从PATH 环境变量中查找文件并执行

定义
int execlp(const char * file,const char * arg,……);

头文件
#include<unistd.h>

说明
execlp()会从PATH 环境变量所指的目录中查找符合参数file的文件名, 找到后便执行该文件, 然后将第二个以后的参数当做该文件的argv[0]、argv[1]……, 最后一个参数必须用空指针(NULL)作结束。

返回值
如果执行成功则函数不会返回, 执行失败则直接返回-1, 失败原因存于errno 中。

相关函数
fork, execl, execle, execv, execve, execvp

错误代码:
参考execve()。

示例

#include<unistd.h>

main()
{
 execlp("ls","ls","-al","/zhmc",(char *)0);

}

输出:


           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述
2016-08-05 00:03:08 struct_slllp_main 阅读数 291
/*************************************************************************************
输入月份和年份返回day of year,就是一年的第几天。
将前几个月加起来,如果闰年,且大于2月份就再加1,在加上当月的天数,就是day of year.  
**************************************************************************************/   
#include <stdio.h>


int xbt_DayOfYear( int year, unsigned char month, unsigned char day )
{  
    int sum=0,flag;/*flag是判断是否是闰年的标志*/      


	switch(month) /*计算输入月份前N个月的总天数*/
	  {  
	  case     1:   sum=0;  
	   break;  
	  case     2:   sum=31;  
	   break;  
	  case     3:   sum=59;  
	   break;  
	  case     4:   sum=90;  
	   break;  
	  case     5:   sum=120;  
	   break;  
	  case     6:   sum=151;  
	   break;  
	  case     7:   sum=181;  
	   break;  
	  case     8:   sum=212;  
	   break;  
	  case     9:   sum=243;  
	   break;  
	  case   10:   sum=273;  
	   break;  
	  case   11:   sum=304;  
	   break;  
	  case   12:   sum=334;  
	   break;  
	  default   :
	   break;  
	  }  
	   
	  sum=sum+day; /*计算总天数*/
	  if((year%400==0)||((year%4==0)&&(year%100!=0)))       
		flag=1; 
	  else  
		flag=0;  
	   
	  if((flag==1)&&(month>2)) 
	  sum++;  
			 
	  return   sum;  
  } 




 int main(int argc, char *argv[])
 {
	unsigned int year = 0, TheDay = 0;
	unsigned char month = 0, day = 0;
	
	printf("请输入年 月 日\r\n");
	scanf("%d %d %d",&year,&month,&day);
	
	TheDay = xbt_DayOfYear(year, month, day);
	printf("%d%02d%02d is the %d day of %d year\n",year,month,day,TheDay,year);
 }

2017-03-26 23:29:32 Quinn0918 阅读数 819
#include <stdio.h>
#include <windows.h>

int is_leap(int year)
{
	if ((year % 4 == 0 || year % 100 ==0) && year % 400 == 0)
	{
		return 1;
	}
	return 0;
}

int main()
{
	int year = 1999;
	if (is_leap(year))
	{
		printf("%d",year);
	}
	else{
		printf("不是闰年");
	}
	
	system("pause");
	return 0;
}

linux C 函数

阅读数 462

linux C 函数

博文 来自: Dopamy_BusyMonkey

日期加一年 SQL

阅读数 4340

Linux C 函数手册

阅读数 1653

没有更多推荐了,返回首页