Linux C 系统编程

1、概述

  • 系统编程:指在操作系统下使用系统调用库函数对资源进行管理
    • 系统调用:操作系统提供给用户程序的一组“特殊的”函数接口
    • 库函数:用户通过应用层库函数的接口,比如fread()对内核的系统调用进行操作
    • 库函数和系统调用的关系:用户使用系统调用时,系统需要转换状态(即用户态和内核态),而这种转换会拉低程序的效率,所以库函数会根据需要设置缓冲区,减少系统调用的次数(即减少系统状态转换的次数),从而提高效率。大多数库函数的本质也是系统调用在这里插入图片描述

除以上两种之外还可以通过shell编程,利用shell解释器操作内核的系统调用

系统调用可以按功能分为以下几种:进程控制、进程间通信、文件系统控制、系统控制、内存管理、网络管理、socket控 制、用户管理。


2、文件操作的系统调用

任何语言都躲不过对文件的操作,所以我们此处先说文件操作。

2.1 文件描述符

  • 概述
    • 系统调用中的I/O函数都是针对文件描述符
    • 文件描述符是非负整数。打开现存文件或新建文件时,系统(内核)会返回一个文件描述 符。文件描述符用来指定已打开的文件。在系统调用(文件IO)中,文件描述符对文件起到标识作用,如果要操作文件,要通过文件描述符来操作
    • 当一个程序运行或者一个进程开启时,系统会自动创建三个文件描述符 ,他们都有对应的宏、文件指针
      0标准输入 STDIN_FILENO、stdin
      1 标准输出 STDOUT_FILENO、stdout
      2 标准输出出错 STDERR_FILENO、stderr

一个程序运行的时候最多可以创建2014个文件描述符,0~1023

文件描述符按照从小到大的顺序依次创建 ,如果中途有文件描述符被关闭了,则再创建的 文件描述符会先补齐之前的,然后依次递增创建 ,注意:不要认为最后创建的文件描述符一定是最大的

2.2 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);  
//(文件不存在时)
  • 功能:打开或者创建一个文件,返回文件描述符
    参数:
    pathname:指定路径的文件名,不指定路径默认为当前路径
    flags:标志位,表明文件的打开方式
    mode:文件权限位,当指定flags中有O_CREAT时,必须有这个参数, 如果没有O_CREAT,则不需要这个参数
    返回值:
    成功:文件描述符
    失败:‐1

flags 的取值:
O_RDONLY:只读方式打开
O_WRONLY:只写方式打开
O_RDWR:可读可写方式打开
用位逻辑或 | 连接多个mode
O_CREAT:文件不存在则创建,使用时需要指定mode权限
O_EXCL:如果同时指定了O_CREAT,且文件已存在,则出错
O_TRUNC:如果文件存在,则清空文件内容
O_APPEND:写文件时,添加到末尾
O_NONBLOCK:当打开的文件是FIFO、字符文件、块文件时此选项为文件标识

mode 的取值:
只有在O_CREAT时使用mode,此参数用于控制权限
使用用八进制数表示,就是属主、属组、其他三类用户权限的124方法表示(1:可读、2:可写、4:可执行)
| 例如,00700表示属主有读、写、执行,属组和其他人没有权限

  • 错误信息的输出使用全局变量errno

#include <errno.h>
errno是一个全局变量,当函数调用失败后,可以通过errno获取错误码
通过一个函数 perror
#include <stdio.h>
​void perror(const char *s);
功能:输出函数调用失败的错误信息
参数:
s:打印错误信息的提示消息
返回值:无

  • 案例
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main (int aygc ,char const* aygv [])
{
	int fd;
	fd = open("file.txt",O_RDONLY);
	//使用open函数以只读方式打开文件file.txt
	//使用fd保存获得的文件描述符
		if(fd == -1)
		//此处用来在打开失败时返回错误信息
		{
	 	//使用全局变量errno打印错误码
		 printf("errno = %d",errno);
	
		//使用perror()输出调用失败
		perror("fail to open");
		return -1;
		}
	printf("fd =%d ",fd);
	return 0;
}

2.3 close()函数

  • 函数原型
 #include  <unistd.h>int close(int fd); 
​​
  • 功能:关闭一个文件描述符
  • 参数:
    fd:指定文件的文件描述符open函数的返回值
  • 返回值:
    成功:0
    ​失败:‐1
  • 案例
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main (int aygc ,char const* aygv [])
{
	int fd;
	fd = open("file.txt",O_RDONLY);

		if(fd == -1)
		//此处用来在打开失败时返回错误信息
		{
	 	//使用全局变量errno打印错误码
		 printf("errno = %d",errno);
	
		//使用perror()输出调用失败
		perror("fail to open");
		return -1;
		}
	printf("fd =%d ",fd);
	//当不在进行任何操作时,使用close()关闭文件描述符
	//一旦关闭文件描述符,该文件描述符失效,即此后该文件描述符不能操作该文件
	return 0;
}

2.4 write()函数

  • 函数原型
 #include <unistd.h> 
ssize_t write(int fd, const void *buf, size_t count);

  • ​功能:向文件写入数据
  • 参数:
    fd:指定的文件描述符
    buf:要写入的数据
    count:要写入的数据的长度
  • 返回值:
    成功:实际写入的字节数
    失败:‐1
  • 案例:向终端写入数据
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main (int argc, char const* argv[])
{
    //使用标准输出的文件描述符(1)向终端写入数据
    if(write(1,"hello word\n",12)==1)
    {//若写入失败输出报错
        perror("fail to write");
        return -1;
    }
    return 0;
}
  • 案例:向文件写入数据
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main (int argc, char const* argv[])
{
    int fd;
    fd = open("file.txt",O_WRONLY|O_CREAT|O_TRUNC,0664);
    //因为不确定文件是否存在,所以参数中使用O_CREAT选项,若文件不存在则创建
    if (fd == -1){perror("fail to open");return -1;}
    ssize_t bytes;//接受write()返回值
    //使用write()写入
    if ((bytes=write(fd,"hello word\n",7))==-1)
    {perror("fail to write");return -1}
    //显示写入成功的位数
    printf("bytes=%d",bytes);

    close(fd);
    return 0;
}

2.5 read()函数

  • 函数原型
#include  <unistd.h> ssize_t read(int fd, void *buf, size_t count); 
  • ​功能:从文件中读取数据
  • 参数:
    ​fd:指定的文件描述符
    ​buf:保存读取到的数据
    ​count:最大一次读取多少个字节
  • 返回值:
    ​成功:实际读取的字节数
    ​失败:‐1
    ​注意:如果读取到文件末尾,返回0
  • 案例:从终端读取数据
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main (int argc, char const* argv[])
{
    //使用标准输入的文件描述符(0)从终端读取数据
    //若你在屏幕上输入的字符数大于第三个参数,则只会读取第三个参数设定个数个字符
    //若你在屏幕上输入的字符数小于第三个参数,则要注意回车表示的换行符也会被读取
    ssize_t bytes;
    char str[32] = "";
    if((bytes = read(0,str,6))==-1)
    {perror("fail to read"); return -1;}

    printf("bytes=%d",bytes);
    printf("str=[%s]",str);
    return 0;
}
  • 案例:从文件中读取数据
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define N 64

int main (int argc, char const* argv[])
{
    int fd;
    fd = open("file.txt",O_WRONLY|O_CREAT|O_TRUNC,0664);
    //因为不确定文件是否存在,所以参数中使用O_CREAT选项,若文件不存在则创建
    if (fd == -1){perror("fail to open");return -1;}
    ssize_t bytes;
    char buf[N]="";
    //使用read()从文件中读取
    if((bytes=read(fd,buf,32))==-1)
    {perror("fail to read");return -1;
    }
    printf("bytes=%d",bytes);
    printf("buf=[%s]",buf);

    //如果想一次性读完全部内容,可以使用循环,以read()的返回值作为判断条件(全部读完再读时返回值为0)

    close(fd);
    return 0;
}

2.6 remove()函数

  • 函数原型
#include <stdio.h> 
int remove(const char *pathname); 

  • 功能:删除指定文件
  • 参数:
    pathname:包含路径的文件名
  • 返回值:
    成功返回0。
    失败返回‐1
  • 案例
#include<stdio.h>
int main (int argc,char const* argv[])
{
if(remove("./file.txt")==-1)
{perroe("fail to remove");
return -1;
}
printf("delete done");
return 0;



未完待续…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值