unix环境编程练习 (2)

网友投稿 612 2022-10-04

unix环境编程练习 (2)

unix环境编程练习 (2)

系统调用

系统调用是由操作系统核心提供,运行于核心态;普通函数调用由库函数或者用户自定义,处于用户态。那些标准函数都是由系统调用完成的。 查看系统调用的接口:

[edemon@CentOS ~]$ man 2

进程不能访问内核,系统调用则是接口,由他们告诉内核进程的请求是什么。

错误码

errno: 1–34存在于: /usr/include/asm-generic/errno-base.h errno: 35–133记录在: /usr/include/asm-generic/errno.h

#define#define#define#define#define EIO 5 /* I/O error#define#define#define ENOEXEC 8 /* Exec format error#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define EADV 68 /* Advertise error#define ESRMNT 69 /* Srmount error#define ECOMM 70 /* Communication error#define EPROTO 71 /* Protocol error#define#define EDOTDOT 73 /* RFS specific error#define#define#define#define#define#define#define#define#define#define#define#define#define ESTRPIPE 86 /* Streams pipe error#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define#define EREMOTEIO 121 /* Remote I/O error#define#define#define#define#define#define#define#define/* for robust mutexes */#define#define#define#define EHWPOISON 133 /* Memory page has hardware error

系统调用部分函数练习

writev

将多个字符串一次性全部写入文件中。 函数相关:

#include ssize_t writev(int fd, const struct iovec *iov, int iovcnt);struct iovec { void *iov_base; /* Starting address */ size_t iov_len; /* Number of bytes to transfer */};The writev() system call writes iovcnt buffers of data described by iov to the file associated with the file descriptor fd ("gather output").The writev() system call works just like write(2) except that

例子:

#include #include #include #include #include #include #include int main(){ char *buff[4]; buff[0] = "My song for you this evening\n"; buff[1] = "It's not to make you sad\n"; buff[2] = "Not for adding to the sorrows\n"; buff[3] = "Over troubled northern land\n"; struct iovec *iov = (struct iovec *)malloc(sizeof(struct iovec)*4); iov[0].iov_base = buff[0]; iov[0].iov_len = strlen(buff[0]); iov[1].iov_base = buff[1]; iov[1].iov_len = strlen(buff[1]); iov[2].iov_base = buff[2]; iov[2].iov_len = strlen(buff[2]); iov[3].iov_base = buff[3]; iov[3].iov_len = strlen(buff[3]); int iovcnt = sizeof(iov); int fd = open("writev.txt",O_RDWR|O_TRUNC|O_CREAT,0644); if(fd == -1){ perror("open "); exit(1); } ssize_t bytes = writev(fd,iov,iovcnt); if(bytes < 0){ perror("writev "); exit(1); } close(fd); free(iov); return 0;}

readv

与writev()相反的函数。它一次能读取数据到多个字符数组中。函数和writev一样。 ​​​ssize_t readv(int fd, const struct iovec *iov, int iovcnt);​​

#include #include #include #include #include #include #include int main(){ char *buff[4]; int i = 0; for(i=0;i<4;i++){ buff[i] = (char *)malloc(40); } struct iovec *iov = (struct iovec *)malloc(sizeof(struct iovec)*4); iov[0].iov_base = buff[0]; iov[0].iov_len = 40; iov[1].iov_base = buff[1]; iov[1].iov_len = 40; iov[2].iov_base = buff[2]; iov[2].iov_len = 40; iov[3].iov_base = buff[3]; iov[3].iov_len = 40; int iovcnt = sizeof(iov); int fd = open("writev.txt",O_RDONLY,0644); if(fd == -1){ perror("open "); exit(1); } ssize_t bytes = readv(fd,iov,iovcnt); if(bytes < 0){ perror("readv "); exit(1); } for(i=0;i<4;i++){ printf("%s",buff[i]); } close(fd); free(iov); return 0;}

执行

[edemon@CentOS workspace]$ gcc readv.c[edemon@CentOS workspace]$ ./a.out My song for you this eveningIt's not to make you sadNot for adding to

lseek, dup

lseek()用于重置光标位置。dup()则是赋值文件描述符。

off_t lseek(int fd, off_t offset, int whence);int dup(int

下面的例子是打开文件txt,描述符是fd,写入”hello world” 复制文件描述符成new_fd,隔行写入”this is new_fd”. 最后读取文件内容。

#include #include #include #include #include #include #include #include int main(){ int fd = open("txt",O_WRONLY|O_CREAT|O_TRUNC,0644); lseek(fd,0,SEEK_SET); char *str = "hello world"; int ret = write(fd,str,strlen(str)); if(ret <= 0){ perror("write to fd"); exit(1); } int new_fd = dup(fd); if(new_fd == -1){ perror("dup "); exit(1); } str = (char *)malloc(50); strcpy(str,"\nthis is new_fd."); ret = write(new_fd,str,strlen(str)); if(ret <= 0){ perror("write to new_fd"); exit(1); } new_fd = open("txt",O_RDONLY); ret = read(new_fd,str,50); if(ret <= 0){ perror("read "); printf("errno is %d\n",errno); exit(1); } printf("%s",str); close(fd); close(new_fd); free(str); return 0;}

执行:

hello worldthis is

poll

poll和select相似,用于等待fd集状态的改变。 ​​​int poll(struct pollfd *fds, nfds_t nfds, int timeout);​​

#include #include #include #include #include #include int main(){ struct pollfd *fds = (struct pollfd*)calloc(2,sizeof(struct pollfd)); fds[0].fd = open("/tmp/test1",O_RDONLY); fds[0].events = POLLIN; fds[1].fd = open("/tmp/test2",O_RDONLY); fds[1].events = POLLIN; int milliSec = 500, i; while(1){ int ret = poll(fds,2,milliSec); if(ret == -1){ perror("poll "); exit(1); } else if(ret == 0){ puts("waiting a short time..."); sleep(3); continue; } else { for(i=0;i

编译运行:

$ ./a.out test1, buff is : hello worldtest2, buff is

access

检查文件是否有相应的权限。​​int access(const char *pathname, int mode);​​​ 比如检查文件/tmp/linux 是否存在:

#include #include #include int main(){ const char *str = "/tmp/linux"; int ret = access(str,F_OK); if(ret == -1){ puts("the file /tmp/linux is not there."); } else { puts("here is /tmp/linux."); } return 0;}

chdir

chdir用以改变程序的工作目录。 ​​​int chdir(const char *path);​​

#include #include int main(){ const char *str1 = "/tmp"; system("pwd"); if(chdir(str1) == -1){ perror("chdir "); exit(1); } system("pwd"); return 0;}

编译执行:

[edemon@CentOS workspace]$ ./a.out /home/edemon/workspace

symlink readlink

symlink用于建立新的(符号)连接,readlink用于查看符号连接内容(对象的名字)。

int symlink(const char *target, const char *linkpath);ssize_t readlink(const char *path, char

正常执行后buff即含有内容信息。

#include #include #include int main(){ const char *str = "./readlink"; symlink("./read",str); char *buff = (char *)calloc(20,1); if(readlink(str,buff,19) == -1){ printf("readlink : %d",errno); exit(1); } printf("read buff: %s",buff); return 0;}

执行:

[edemon@CentOS workspace]$ ./a.out read buff: read[edemon@CentOS workspace]$ ls -l readlinklrwxrwxrwx. 1 edemon edemon 4 Dec 15 20:19 readlink -> read

link

link创建一个文件的(硬)连接。 ​​​int link(const char *oldpath, const char *newpath);​​

#include #include #include #include int main(){ if(link("./test.txt","./test2.txt") == -1){ printf("link errno is %d\n",errno); exit(1); } system("ls -l |grep test"); return 0;}

软连接和硬连接的区别:如果将源文件删除了,软连接文件是不能访问的,但是硬连接文件仍然正常;软连接可以跨磁盘分区,但是硬连接不能。

remove

​​int remove(const char *pathname);​​​ 如果pathname是一个文件,unlink会被调用;如果pathname是文件夹,那么rmdir则会被调用。

#include #include int main(){ int tag = 0; tag = tag|remove("./test_dir"); tag = tag|remove("./test"); if(tag == 0){ printf("remove test_dir and test.txt ok.\n"); } else printf("remove failed.\n"); return 0;}

opendir readdir

​​DIR *opendir(const char *name);​​​ DIR*是一种目录流。 ​​​struct dirent *readdir(DIR *dirp);​​​ readdir的返回值是指向struct dirent的指针。

struct dirent { ino_t d_ino; /* inode number */ off_t d_off; /* not an offset; see NOTES */ unsigned short d_reclen; /* length of this record */ unsigned char d_type; /* type of file; not supported by all filesystem types */ char d_name[256]; /* filename */

在dirent.h中说明了d_type:

/* File types for `d_type'. */enum { DT_UNKNOWN = 0,# define DT_UNKNOWN DT_UNKNOWN DT_FIFO = 1,# define DT_FIFO DT_FIFO DT_CHR = 2,# define DT_CHR DT_CHR DT_DIR = 4,# define DT_DIR DT_DIR DT_BLK = 6,# define DT_BLK DT_BLK DT_REG = 8,# define DT_REG DT_REG DT_LNK = 10,# define DT_LNK DT_LNK DT_SOCK = 12,# define DT_SOCK DT_SOCK DT_WHT = 14# define DT_WHT DT_WHT

查找当前目录下所有的文件夹:

#include #include #include #include int main(){ DIR* here = opendir("./"); struct dirent *dir = NULL; while((dir=readdir(here)) != NULL){ if(dir->d_type == 4) printf("type of file is dir, name of file is %s\n",dir->d_name); } return 0;}/*$ ./a.out type of file is dir, name of file is ..type of file is dir, name of file is .type of file is dir, name of file is mydirtype of file is dir, name of file is codetype of file is dir, name of file is .metadatatype of file is dir, name of file is test_dir*/

index, rindex

index用于寻找字符串中第一个出现的指定字符串。 ​​​char *index(const char *s, int c);​​​ rindex用于查找字符串中最后一个出现的指定字符。 ​​​char *rindex(const char *s, int c);​​

#include #include #include int main(){ const char* str = "0123456789"; char* dex = index(str,'4'); printf("%s\n",dex); return 0;}/*$ ./a.out 456789*/

和index相似的函数memchr用于在s所指内存中前n个字节查找有木有c存在。​​void *memchr(const void *s, int c, size_t n);​​

memmove

​​void *memmove(void *dest, const void *src, size_t n);​​​ 内存拷贝函数memmove和memcpy都是用于复制src前n个字节到dest中.

#include #include #include int main(){ const char* str = "01234543210"; printf("first location of 4: %s\n",index(str,'4')); printf("last location of 4: %s\n",rindex(str,'4')); return 0;}/*$ ./a.out first location of 4: 4543210last location of 4: 43210*/

strcasecmp

strcasecmp()是一个可以忽略大小写比较的函数,这在某些数据库密码验证中很有用。 ​​​int strcasecmp(const char *s1, const char *s2);​​​ 例如:

#include #include int main(){ const char* str1 = "ASdF"; const char* str2 = "asDf"; if(strcasecmp(str1,str2) == 0) printf("%s is same as %s\n",str1,str2); return 0;}/*./a.out ASdF is same as asDf*/

strcspn, strspn

​​size_t strcspn(const char *s, const char *reject);​​​ strcspn用于统计源字符串s中不含指定字符串reject中字符的连续字符个数。 ​​​size_t strspn(const char *s, const char *accept);​​​ 与之相反是strspn,它用于统计包含accept字符串中字符的连续字符的个数。

#include #include #include int main(){ const char* str1 = "a34b_c2>?<2dfh.L"; printf("the length of continuous string without '._?<' is %d\n",strcspn(str1,"._?<")); printf("the length of continuous string without '_c2a43' is %d\n",strspn(str1,"_c2a43")); return 0;}/*./a.out the length of continuous string without '._?<' is 4the length of continuous string without '_c2a43' is 3

strdup

strdup会先malloc出一块内存,然后将字符串拷贝到该内存,最后将相应的指针返回。该内存可以被free.

#include #include #include int main(){ const char* str = "hello world"; char* new = strdup(str); printf("%s\n",new); free(new); return 0;}/*$ ./a.outhello world*/

strpbrk

​​char *strpbrk(const char *s, const char *accept);​​​ strpbrk()用于查找在s中第一个出现在accept中的字符的位置。

#include #include #include int main(){ const char* s = "0123456789"; printf("for 2: %s\n",strpbrk(s,"a2")); printf("for 4: %s\n",(char *)strpbrk(s,"b4")); return 0;}/*./a.out for 2: 23456789for 4: 456789*/

strstr

​​char *strstr(const char *haystack, const char *needle);​​​ strstr用于确定子字符串的位置。和index相比,第二个参数不是char,而是string.

strtok

​​char *strtok(char *str, const char *delim);​​​ strtok()用于将字符串分割成不同的片段,它在参数s字符串中发现delim中的字符后将之变成0,第一次调用时必须给于str字符串参数,之后的调用将其设置成NULL,每一次调用成功将会返回下一个指向待分割字符串的指针。

#include #include int main(int argc,char *argv[]){ printf("%s\n",strtok(argv[1],argv[2])); char *p = NULL; while((p = strtok(NULL,argv[2])) != NULL) printf("%s\n",p); return 0;}/*edemon@ubuntu1:~/workspace$ gcc -o strtok strtok.cedemon@ubuntu1:~/workspace$ ./strtok 12-34.45-78.90-11 .-123445789011*/

ctime

​​char *ctime(const time_t *timep);​​​ ctime用于将指向time_t的指针信息转化成字符串时间格式。我们需要先获取它的参数,可以通过​​​time_t time(time_t *t);​​​实现,​​time() returns the time as the number of seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).​​

#include #include #include int main(){ time_t time_p; time(&time_p); printf("%s",ctime(&time_p)); return 0;}/*$ ./a.out Tue Dec 20 21:47:00 2016*/

字符串转化成数值

function

format

introduce

atof

double atof(const char *nptr);

convert a string to a double

atoi

int atoi(const char *nptr);

convert a string to an int integer

atol

long atol(const char *nptr);

convert a string to an long integer

atoll

long long atoll(const char *nptr);

convert a string to an long long integer

gcvt

​​char *gcvt(double number, size_t ndigit, char *buf);​​​ 浮点数转化成字符串,四舍五入。函数返回buf指针所指空间。

#include #include int main(){ double number = 123.456; char* buf = (char* )malloc(10); printf("3 digits: %s\n",gcvt(number,3,buf)); printf("4 digits: %s\n",gcvt(number,4,buf)); printf("5 digits: %s\n",gcvt(number,5,buf)); return 0;}/*./a.out 3 digits: 1234 digits: 123.55 digits: 123.46*/

toascii

​​int toascii(int c);​​​ toascii()用于将参数c转化成转化成7位无符号char型数值,参数的高位将被抹去。 比如:

#include #include #include int main(){ int a = toascii(1<<8); printf("2^8: %d(%c)\n",a,a); a = toascii((1<<8)-1); char str[5]; str[0] = a; str[1] = 0; printf("2^8-1: %d(%s)\n",a,str); return 0;}/*./a.out 2^8: 0()2^8-1: 127)*/

1000000002⟶010⟶NUL0111111112⟶12710⟶DEL 让我感觉奇怪的是DEL不是删除右边字符吗,为什么这里变成删除左边的(了?

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:lightOJ 1236 Pairs Forming LCM(算术基本定理)
下一篇:小程序开发之组件之间的传值方法(代码示例)(小程序调用组件方法)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~