Unix_Linux环境c语言(一)

本周主要对环境介绍,文件操作与文件管理进行了学习。

一、静态库、共享库、动态加载共享库的创建和应用

静态库

1、创建静态库
		编写源代码:vi .c/.h
		编译源代码:gcc -c xxx.c -> xxx.o
		打包生成静态库:ar -r libxxx.a x1.o x2.o ...
		ar命令的一些参数:
			-r 把目标文件添加到静态库中,已经存在的更新
			-q 将目标文件追加到静态库的末尾
			-d 从静态库中删除目标文件
			-t 显示静态库中有哪些目标文件
			-x 把静态库拆分成目标文件
	2、调用静态库
		直接调用:调用者要和库在同一路径下
			gcc main.c libxxx.a
		设置环境变量:设置方法与C_INCLUDE_PATH类似
			1.打开 vim ~/.bashrc 文件
			2.在文件末尾添加一行
				export LIBRARY_PATH=$LIBRARY_PATH:库文件的路径
			3.重新加载配置文件 source ~/.bashrc
			4.编译时要指定库名
				gcc main.c -lmath
		设置编译参数:-L路径
			gcc main.c -L路径 -lmath	
	3、运行
		在编译时已经把被函数的二进制复制到可执行文件中了,在执行时不再需要静态库文件。

共享库

1、创建共享库
		编写源代码:vi .c/.h
		编译出位置无关目标文件:
			gcc -c -fpic xxx.c -> xxx.o
		链接生成共享库:
			gcc -shared x1.o x2.o x3.0 ... -o libxxx.so
	2、调用共享库
		直接调用:调用者要和库在同一路径下
			gcc main.c libxxx.so
		设置环境变量:设置方法与C_INCLUDE_PATH类似
			1.打开 vim ~/.bashrc 文件
			2.在文件末尾添加一行
				export LIBRARY_PATH=$LIBRARY_PATH:库文件的路径
			3.重新加载配置文件 source ~/.bashrc
			4.编译时要指定库名
				gcc main.c -lmath
		设置编译参数:-L路径
			gcc main.c -L路径 -lmath	
	3、运行
		在使用共享库时,调用者只是记录了被代码在库的位置,因此在执行时需要共享库同时被加载。
		操作系统会根据LD_LIBRARY_PATH环境变量的设置来加载共享库。

动态加载共享

#include <dlfcn.h>
	1、加载共享库
	void *dlopen(const char *filename, int flag);
	filename:共享库的库名,或路径
	flag:
		RTLD_LAZY 使用时才加载
		RTLD_NOW 立即加载
	返回值:共享库的句柄(类似文件指针)
	
	2、获取标识符地址并使用
	void *dlsym(void *handle, const char *symbol);
	handle:共享库的句柄
	symbol:标识符的名字
	返回值:标识符在共享库中的位置(地址,可以解引用,或跳转过去)。
	3、卸载共享库
	int dlclose(void *handle);
	handle:共享库的句柄
	返回值:成功返回0,失败返回-1
	
	4、获取错误信息
	char *dlerror(void);
	返回值:会把在使用共享库的过程中出现的错误,以字符串形式返回

二、环境变量的获取与修改

1、环境变量表
	每个程序运行时操作系统都会把所有的环境变量记录到一张表中,传给程序。
	通过main函数参数
		获取int main(int argc, char* argv[],char* environ[])
	通过声明全局变量来获取
		extern char** environ;
2、环境变量函数
	char * getenv(const char *name);
	功能:根据环境变量名,获取环境变量的值
	int putenv (char *string):
	功能:以name=value形式设置环境变量,如果name存在则更新,不存在就加载。
	返回值:成功返回0,失败返回-1
	int setenv (const char *name,const char *value,int overwrite);
	功能:设置name环境变量的值为value,如果name存在且overwrite不为零则更新,否则不变。
	int unsetenv(const char *name);
	功能:从环境变量表中删除name
	int clearenv(void);
	功能:清空环境变量表。
	操作系统记录的环境变量的数据记录一块特殊的存储空间,而在程序自己添加的环境变量需要自己准备存储空间。
	注意:对于环境变量的修改,只能影响自己,不能影响别人。

三、系统调用IO

系统IO与标准IO的区别:

因为标准IO使用了缓冲技术,当数据写入时并没有立即把数据交给内核,而是先放在缓冲区中,当缓冲区满时,会一次性把缓冲区中的数据交给内核写入到文件中,这样就减少内核态与用户态的切换次数。
而系统IO每写一次数据就要进入一次内核态,这样就浪费了大量时间进行内核态与用户态的切换,因此用时更长。
如果为系统IO设置更大的缓冲区,它会比标准IO更快

int open(const char *pathname, int flags);
功能:打开文件

int open(const char *pathname, int flags, mode_t mode);
功能:创建文件

int close(int fd);
功能:删除文件

ssize_t read(int fd, void *buf, size_t count);
功能:从文件中读取数据到内存

ssize_t write(int fd, const void *buf, size_t count);
功能:把数据写入到文件

off_t lseek(int fd, off_t offset, int whence);
功能:设置当前文件位置指针

int dup(int oldfd);
功能:复制文件描述符,操作系统会从未使用的文件描述符中选择一个返回。

int dup2(int oldfd, int newfd);
功能:复制指定的文件描述符,如果newfd已经被使用,则先关闭,再复制。

void sync(void);
功能:把所有缓冲区中的数据全部同步到磁盘

int fsync(int fd);
功能:指定fd文件的缓冲区数据同步到磁盘,只针对一个文件,数据同步到磁盘后才返回。

int fdatasync(int fd);
功能:指定fd文件的缓冲区数据同步到磁盘,但仅是文件的数据,并不同步文件属性。

int fcntl(int fd, int cmd, long newfd);
cmd:F_DUPFD
功能:复制文件描述符,与fd操作同一个文件

int fcntl(int fd, int cmd,void/long );
功能:设置或获取文件描述符标志
cmd:F_GETFD void

int fcntl(int fd, int cmd,void/long );
功能:获取文件状态标志(此文件打开的权限以及打开的方式)
cmd:
F_GETFL void
O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC 不能获取到
返回值:带有文件状态标志的int类型变量,需要与各种标志 & 得到
F_SETFL long
O_APPEND, O_ASYNC,O_DIRECT, O_NOATIME,O_NONBLOCK 仅能设置的

int fcntl(int fd, int cmd,struct* flock );
功能:为文件加锁,能锁整个文件或者一部分内容
一旦进程关闭,锁会自动取消。
cmd:
F_GETLK 获取锁的信息
F_SETLK 设置文件锁
F_SETLKW 测试锁
注意:加锁并不能让其他进程打不开文件或不能操作,而是使用者都要遵守锁的约定,确保文件不混乱。

int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
功能:用来获取文件的属性,返回值:成功返回0,失败返回-1

int access(const char *pathname, int mode);
功能:测试当前用户对文件的访问权限,或者文件是否存在。

mode_t umask(mode_t mask);
功能:设置并获取权限屏蔽码,功能与umask命令一样

int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
功能:修改文件的权限,成功返回0,失败返回-1。
注意:它们不受权限屏蔽码的干扰。

int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
功能:修改文件的大小,成功返回0,失败返回-1。

int link(const char *oldpath, const char *newpath);
功能:创建硬链接文件,硬链接指向的是文件的内容,因此当链接目标被删除后,依然可以访问文件的内容。

int unlink(const char *pathname);
功能:删除硬链接文件

int remove(const char *pathname);
功能:删除文件,该函数是标准库中的珊瑚文件函数,底层调用了unlink系统调用。

int rename(const char *oldpath, const char *newpath);
功能:文件重命名

int symlink(const char *oldpath, const char *newpath);
功能:创建一个软链接(目录只能创建软链接)

ssize_t readlink(const char *path, char *buf, size_t bufsiz);
功能:读取软链接文件的内容而非链接目标(open打开软链接文件时,打开的是目标文件)。

int mkdir(const char *pathname, mode_t mode);
功能:创建目录,目录一定要有执行权限,否则无法进入。

int rmdir(const char *pathname);
功能:删除空目录

char *getcwd(char *buf, size_t size);
功能:获取当前进程的工作目录,工作目录是指当不加路径信息时,创建/打开时从那个目录下查找,工作目录默认是程序所在的目录。

int chdir(const char *path);
功能:修改进程的工作目录

int fchdir(int fd);
功能:修改进程的工作目录

DIR *opendir(const char *name);
功能:打开一个目录流

DIR *fdopendir(int fd);
功能:使用文件描述符获取目录流,fd必须是目录文件的

int closedir(DIR *dirp);
功能:关闭目录流

void rewinddir(DIR *dirp);
功能:把目录流的位置指针调整到开头

long telldir(DIR *dirp);
功能:获取当前目录流的位置指针在第几个文件结点

void seekdir(DIR *dirp, long offset);
功能:调整当前目录流的位置指针。

通过上述的学习,实现了一下两个程序
实现ls -l的功能

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pwd.h>
#include <dirent.h>
#include <grp.h>
#include <string.h>
#include <time.h>

char* file_mode(mode_t m,char* str)
{
	if(S_ISREG(m))
		str[0] = '-';
	else if(S_ISDIR(m))
		str[0] = 'd';
	else if(S_ISCHR(m))
		str[0] = 'c';
	else if(S_ISBLK(m))
		str[0] = 'b';
	else if(S_ISFIFO(m))
		str[0] = 'q';
	else if(S_ISLNK(m))
		str[0] = 'l';
	else if(S_ISSOCK(m))
		str[0] = 's';
	else 
		str[0] = '?';

	str[1] = '\0';

	strcat(str,S_IRUSR&m?"r":"-");
	strcat(str,S_IWUSR&m?"w":"-");
	strcat(str,S_IXUSR&m?"x":"-");

	strcat(str,S_IRGRP&m?"r":"-");
	strcat(str,S_IWGRP&m?"w":"-");
	strcat(str,S_IXGRP&m?"x":"-");
	
	strcat(str,S_IROTH&m?"r":"-");
	strcat(str,S_IWOTH&m?"w":"-");
	strcat(str,S_IXOTH&m?"x":"-");

	return str;
}

int file_number(mode_t m,char* str)
{
	int num=2;
	if(S_ISDIR(m))
	{
	 	DIR *dp = opendir(str);
		chdir(str);
		if (NULL == dp)
		{
			return num;
		}
		for(struct dirent* de = readdir(dp);NULL != de;de =readdir(dp))
		{
			if (strcmp(".",de->d_name)==0) continue;
			if (strcmp("..",de->d_name)==0) continue;
			int fd = open(de->d_name,O_RDONLY);
			struct stat buf;
			fstat(fd,&buf);
			if(S_ISDIR(buf.st_mode))
			{
				num++;
			}
		}
		chdir("..");
		return num;
		
	}
	return 1;
}

char* file_time(time_t t,char* str)
{
	struct tm* it = localtime(&t);
	sprintf(str,"%2d月 %02d %02d:%02d",it->tm_mon+1,it->tm_mday,it->tm_hour,it->tm_min);
	return str;
}

char* file_uid(uid_t uid,char* str)
{
	struct passwd* wd = getpwuid(uid);
	strcpy(str,wd->pw_name);
	return str;
}

char* file_gid(gid_t gid,char* str)
{
	struct group* gr = getgrgid(gid);
	strcpy(str,gr->gr_name);
	return str;
}

int main()
{
	DIR *dp = opendir(".");
	if (NULL == dp)
	{
		perror("opendir");
		return -1;
	}
	for(struct dirent* de = readdir(dp);NULL != de;de =readdir(dp))
	{
		if (strcmp(".",de->d_name)==0) continue;
		if (strcmp("..",de->d_name)==0) continue;
		int fd = open(de->d_name,O_RDONLY);
		char str_mode[255]={},str_time[255]={},str_uid[255]={};
		char str_gid[255]={};
		struct stat buf;
		fstat(fd,&buf);
		printf("\e[0;30m""%s ",file_mode(buf.st_mode,str_mode));//文件权限
		printf("%d ",file_number(buf.st_mode,de->d_name));//文件数量
		printf("%s ",file_uid(buf.st_uid,str_uid));//文件用户id
		printf("%s ",file_gid(buf.st_gid,str_gid));//文件用户gid
		printf("%5lu ",buf.st_size);//文件大小
		printf("%s ",file_time(buf.st_mtime,str_time));//文件时间
		if(S_ISDIR(buf.st_mode))
		{	
			printf("\e[1;34m""%s\n",de->d_name);//目录名称
		}
		else if (strcmp("a.out",de->d_name)==0)
		{
			printf("\e[1;32m""%s\n",de->d_name);//a.out文件名称
		}
		else
		{
			printf("\e[0;30m""%s\n",de->d_name);//文件名称
		}
	}
	printf("\e[0;30m""\n");
}

实现rm -rf的功能(删除非空目录)

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>

void delete_file(char *str)
{
	DIR * dp = opendir(str);
	if (NULL ==dp)
		return ;
	chdir(str);
	for(struct dirent* de = readdir(dp);NULL != de;de =readdir(dp))
	{
		if (strcmp(".",de->d_name)==0) continue;
		if (strcmp("..",de->d_name)==0) continue;
		int fd = open(de->d_name,O_RDONLY);
		struct stat buf;
		fstat(fd,&buf);
		if(S_ISDIR(buf.st_mode))
		{
			delete_file(de->d_name);
			chdir("..");
			rmdir(de->d_name);
		}
		else 
		{
			remove(de->d_name);
		}
	}
}



int main()
{
	char str[255]={};
	printf("请输入要删除的文件");
	gets(str);
	int fd =open(str,O_RDONLY);
	struct stat buf;
	fstat(fd,&buf);
	if(S_ISDIR(buf.st_mode))
	{
		delete_file(str);
		chdir("..");
		rmdir(str);
	}
	else
	{
		remove(str);
	}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值