2015-09-03 22:19:39 NK_test 阅读数 2081

I/O是什么

输入/输出是内存和外设之间拷贝数据的过程:

   设备->内存: 输入操作

   内存->设备: 输出操作

 高级I/O: ANSI C提供的标准I/O库函数成为高级I/O, 也称为带缓冲的I/O;

 低级I/O: Linux 提供的系统调用通常也称为不带缓冲的I/O;

文件描述符

  在linux系统中打开文件就会获得文件描述符,它是个很小的正整数。每个进程在PCBProcess Control Block)中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针。一个进程启动时,默认打开了3个文件,标准输入、标准输出、标准错误,对应的文件描述符是0(STDIN_FILENO)、1(STDOUT_FILENO)、2(STDERR_FILENO),这些常量定义在unistd.h头文件中。注:括号内的就代表文件指针File*。

文件描述符和文件指针的转换函数

fileno: 将文件指针转换成文件描述符

       int fileno(FILE *stream);

fdopen: 将文件描述符转换成文件指针

       FILE *fdopen(int fd, const char *mode);

int main()
{
	printf("fileno(stdin)= %d\n",fileno(stdin));
	// res: fileno(stdin)=0
} 

基本API

1.open
打开成功返回文件描述符;打开失败返回-1。

int open(const char *pathname, int flags, mode_t mode); 

参数:

   pathname:  文件名, 可以包含[绝对/相对]路径名;

   flags: 文件打开模式;

   mode: 用来指定对文件所有者, 文件用户组以及系统中的其他用户的访问权限;


#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#define ERR_EXIT(m) \
        do \
        { \
            perror(m); \
            exit(EXIT_FAILURE); \
        }while(0)

int main()
{  
   int fd;
   umask(0);
   fd=open("test.txt",O_RDONLY,0666);
   if(fd==-1)
   ERR_EXIT("open failure");
   printf("Open OK!\n");
   return 0;
}

注意两点:

  1.我们使用#define定义出错的函数,这样更加专业

  2.umask是从我们定义的权限中再“拿走”相应的位,注意这里是逻辑减。我们定义权限666,系统一般默认umask是022(使用umask命令查看),所以剩下的是644,我们也可以将umask的值置为0,这样在程序中就不受其影响了。

2.close

  int close(int fd);

  关闭文件描述符, 使得文件描述符得以重新利用,一个进程结束时也会主动关闭所有的文件。

3.read

    ssize_t read(int fd, void *buf, size_t count);

  返回从文件复制到缓冲区的字节数,count:从该文件复制到buf的字节个数。

4.write

    ssize_t write(int fd, const void *buf, size_t count);  

返回值:

   错误: -1

   什么都没做: 0

   成功: 返回成功写入文件的字节数

注意:

   write返回大于0时, 并不代表buf的内容已经写入到磁盘上的文件中了, 其仅仅代表buf中的数据已经copy到相应的内核缓冲区了. 要实现将缓冲区的内容真正”冲洗”到磁盘上的文件, 需要调用fsync函数;

     int fsync(int fd);

   其将内核缓冲区中尚未写入磁盘的内容同步到文件系统中;

   其实在open调用的时候也可以指定同步选项:O_SYNC  O_SYNC The file is opened for synchronous I/O.   Any  write(2)s  on  the  resulting  file  descriptor will block the calling process until the data has been physically written to the underlying hardware.

   write会等到将buf的内容真正的写入到磁盘才真正返回;

#define ERR_EXIT(m) \
        do \
        { \
            perror(m); \
            exit(EXIT_FAILURE); \
        }while(0)

int main()
{  
   int fd;
   umask(0);
   fd=open("test.txt",O_RDONLY,0666);
   if(fd==-1)
   ERR_EXIT("open failure");
   printf("Open OK!\n");
    int outfd;
   outfd=open("temp.txt",O_RDWR | O_CREAT,0666);
   if(outfd==-1)
   {
       ERR_EXIT("open dest error");
   }
   char buff[1024];
   int nread;
   while((nread=read(fd,buff,1024))>0)
   write(outfd,buff,nread);
   close(fd);
   close(outfd);
   return 0;
}

实现了简单的cp功能。

5.lseek

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

Whence取值:

SEEK_SET

   The offset is set to offset bytes.

SEEK_CUR

   The offset is set to its current location plus offset bytes.

SEEK_END

   The offset is set to the size of the file plus offset bytes.

int ret =lseek(fd,0,SEEK_CUR);
 printf("current offset =%d\n",ret);

6。目录访问之opendir,readdir

DIR *opendir(const char *name);  //打开一个目录

struct dirent *readdir(DIR *dirp);

int closedir(DIR *dirp);  //关闭目录

int mkdir(const char *pathname, mode_t mode);  //创建目录

int rmdir(const char *pathname);  //删除一个空目录

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结构的指针, 它包含指定目录的下一个连接的细节;
失败:NULL


 DIR* dir=opendir(".");
   struct direnn *de;
   while((de=readdir(dir))!=NULL)
   {
       if(strncmp(de->d_name,".",1)==0)
           continue;
       printf("%s\n",de->d_name);
   
   closedir(dir);
   exit(EXIT_SUCCESS);

上面代码的功能是实现简单的ls操作,列出目录下的普通文件。





2013-09-15 18:05:41 a1222234 阅读数 1687
自己的思考:其实其他语言实现的功能,只要是在windows上进行开发的,他们最终都需要直接或间接的调用windows api才能实现软件的功能,因为在windows上运行的所有软件,无论是什么语言编写的,最终都是由windows API提供的功能实现的。(即使是windows上的c语言函数也是调用windows的api实现的。)
类似的,在linux上运行的所有软件,无论是什么语言编写的,最终都是调用的linux提供的API来实现功能的。


疑问:话又说回来,那windows API又是什么语言实现的呢?linux API呢?
那位大侠知道?请不吝赐教,共同进步!


-------------------------
网上的回答:
JAVA API是由JAVA虚拟机进行编译,虚拟机会将你的这些JAVA API转换为WINDOWS API 或对应的二进制代码(如果在其它操作系统平台上,则转为其它平台API)。


Windows API 是由windows  操作系统提供的,是用来与操作系统进行对话的。
参考:http://zhidao.baidu.com/link?url=Z1DCkkmKEj7iw6xfuDerh7-t7lP3-WderTM9LNtTR7ATi9g7YUyX23jB75ol68BQAWQdOp7Nq_kZeYgw0eLuRa
2018-10-17 17:03:58 SHNU_PFH 阅读数 3454
2018-07-08 12:29:27 qq_33575901 阅读数 1892

一、标准IO函数:

打开普通文件:fopen                                                        错误输出函数:perror          stdreror     

按字符输入输出函数:fgetc   fputc                                     按行输入输出函数:fgets          fputs         

按指定单位读写文件:fwrite     fseek                                  定位流:fseek                                                  关闭流:fclose

格式化输入输出函数:fprintf    fscanf                                  sprintf       sscanf            

判断fgetc的返回结果函数:feof  

二、文件IO函数:

头文件:sys/types.h  sys/stat.h    fcntl.h       unistd.h

打开文件:open                                                                 读写文件:read            write

打开目录:opendir                                                             读写目录:readir

定位文件:lseek                                                                 获取文件信息:stat

三、进程编程函数

头文件:sys/types.h   unistd.h       stdlib.h

创建进程:fork                                                                   在一个进程中执行另一个程序:execl

退出进程:exit                  _exit                                           子进程不退出,阻塞父进程:wait            waitpid

四、线程编程函数

头文件:pthread.h     semaphore.h          

创建线程:pthread_create                                                   退出线程:pthread_exit

若没线程结束则阻塞:pthread_join(线程ID,NULL)

线程同步:int sem_init初始化信号量        int sem_wait:获取信号量,不成功则阻塞(P操作)  int sem_post:释放信号量  (V操作)

线程互斥:pthread_mutex_init:创建互斥锁           pthread_mutex_lock:加锁            pthread_mutex_unlock:解锁

五、管道通信

头文件:sys/types.h     sys/state.h       unistd.h

管道函数名:pipe                                                            有名管道函数:mkfifo

六、信号函数:

头文件:sys/types.h   signal.h           unistd.h    

处理信号函数:signal                      发送信号函数:kill                    设置定时器:alarm

七、建立共享内存函数

头文件:sys/types.h   sys/ipc.h      sys/shm.h

指定建立ipc通讯所需的ID:ftok                         创建共享内存:shmget                   映射共享内存:shmat

删除映射地址:shmdt                                         释放结构体变量:shmctl

八、消息队列

头文件:sys/types.h      sys/ipc.h        sys/shm.h

创建消息队列:msgget                                                                  发送消息:msgnd                    

接收消息:msgrcv                                                                         控制消息:msgctl

2018-10-03 13:51:36 fight5_j 阅读数 1892

1、open()

头文件:#include <unistd.h>

函数原型:int open(const char *pathname, int flags);

 int open(const char *pathname, int flags, mode_

t mode);

函数说明:flags打开文件方式

 mode创建文件夹的权限

返回值:成功返回文件描述符,失败返回-1

2、close()

头文件:#include <unistd.h>

函数原型:int close(int fd);

返回值:成功返回0,失败返回-1.

3、read()

头文件:#include <unistd.h>

函数原型:size_t read(int fd, void *buf, size_t count);

返回值:成功返回读取的字节数,返回0则读取结束。

4、write()

头文件:#include <unistd.h>

函数原型:size_t write(int fd, const void *buf, size_t

count);

返回值:成功返回写入的字节数,失败返回-1。

5、ioctl()

头文件:#include <sys/ioctl.h>

函数原型:int ioctl(int fd, int request);

函数说明:ioctl()提供了一个用于控制设备及其描述符的和配置底层服务的接口。

返回值:成功返回0,失败返回-1。

6、fork()

头文件:#include <unistd.h>

函数原型:pid_t fork();

返回值:成功,父进程返回子进程pid,子进程返回0,失败-1。

7、getpid()

头文件:#include <unistd.h>

函数原型:pid_t getpid();

函数说明:获得调用进程的ID。

8、getppid()

头文件:#include <unistd.h>

函数原型:pid_t getppid();

函数说明:获得父进程的ID。

9、exit()

头文件:#include <stdlib.h>

函数原型:void exit(int status);

10、_exit()

头文件:#include <unistd.h>

函数原型:void _exit(int status);

函数说明:status 返回的状态。

11、wait()和waitpid()

头文件:#include <sys/wait.h>

函数原型:pid_t wait(int *status);

 pid_t waitpid(pid_t pid, int *status, int    options);

12、exec函数族

头文件:#include <unistd.h>

函数原型:

int execl(const char *path, const char *arg, ...);

int execv(const char *path, char *const argv[]);

int execle(const char *path, const char *arg, ..., char   *const envp[]);

int execve(const char *path, char *const argv[], char *const

 envp[]);

int execlp(const char *file, const char *arg, ...);

int execvp(const char *file, char *const argv[]);

函数说明:

(1)前4个取路径名作为参数,后两个取文件名作为参数。

(2)与参数传递有关(l表示list,v表示vector)。execl、execlp 以及execle要求将新程序的每个命令行参数(command-line arguments )都指定为一个单独的参数,以NULL指针表明参数的 结束。另外三个函数(execv、execvp和execve),首先须要建立 一个指向各参数的指针数组,然后将该数组的地址作为这三个函 数的参数。

(3)与向新程序传递环境变量表有关。以e结尾的两个函数 (execle和execve)可以传递一个指向环境字符串指针数组的指 针。其它四个函数则使用调用进程中的environ变量为新进程复 制现有的环境。

13、kill() //发送信号

头文件:#include <signal.h>

函数原型:int kill(pid_t pid, int sig);

函数说明:pid 发送信号的目标进程

 sig 信号的类型

返回值:成功 0,失败 -1.。

14、raise()//进程给自己发信号

头文件:#include <signal.h>

函数原型:int raise(int sig);

15、alarm()//一段时间后给自己发送SIGALRM信号

头文件:#include <unistd.h>

函数原型:unsigned int alarm(unsigned int seconds);

16、signal()//信号处理

头文件:#include <signal.h>

函数原型:sighandler_t signal(int signum, sighandler_t   handler);

17、sigaction()//POSIX标准

头文件:#include <signal.h>

函数原型:int sigaction(int signum, const struct sigaction    *act,struct sigaction *oldact);

函数说明:act表示要设置的对信号的新处理方式。

 oldact表示原来对信号的处理方式。

返回值:函数执行成功返回0,失败返回-1。

18、pipe()//普通管道

头文件:#include <unistd.h>

函数原型:int pipe(int filedes[2]);

函数说明:写到filedes[1]的所有数据都可以从filedes[0]读回来。

19、mkfifo()//命名管道

头文件:#include <unistd.h>

函数原型:int mkfifo(const char *pathname, mode_t mode);

  1. semget() (System V信号量)

头文件:#include <sys/types.h>

  #include <sys/ipc.h>

        #include <sys/sem.h>

函数原型:int semget(key_t key, int nsems, int semflg);

函数说明:该函数的作用是创建一个新信号量或取得一个已有信  号量的键。参数key是一个整数值,不相关的进程可  以通过它访问同一个信号量。程序对所有信号量的访  问都是间接的,它先提供一个键,再由系统生成一个  相应的信号量标识符。只有 semget函数才能直接使  用信号量键,所有其他的信号量函数都是使用 semget  函数返回的信号量标识符。

21、semop()

头文件:#include <sys/types.h>

  #include <sys/ipc.h>

  #include <sys/sem.h>

函数原型:int semop(int semid, struct sembuf *sops, unsigned     nsops);

函数说明:该函数用于改变信号量的值。

22、semctl()

头文件:#include <sys/types.h>

  #include <sys/ipc.h>

  #include <sys/sem.h>

函数原型:int semctl(int semid, int semnum, int cmd, ...);

函数说明:该函数用来控制信号量信息。

23、shmget()

头文件:#include <sys/ipc.h>

  #include <sys/shm.h>

函数原型:int shmget(key_t key, size_t size, int shmflg);

函数说明:与信号量一样,程序需要提供一个参数key,它有效 地为共享内存命名。shmget函数返回一个共享内存标识符, 该标识符用于后续的共享内存函数。参数size以字节为单 位指定需要共享的内存容量。参数 shmflg包含9个比特 的权限标志,它们的作用与创建文件时使用的 mode标志 一样。

24、shmat()

头文件:#include <sys/ipc.h>

    #include <sys/shm.h>

函数原型:void *shmat(int shmid, const void *shmaddr, int   shmflg);

函数说明:第一次创建共享内存段时,它不能被任何进程访问。 要想启用对该共享内存的访问,必须将其连接到一个进程的地址 空间中,这项工作由shmat函数完成。

shmid是由shmget返回的共享内存标识符。

shmaddr指定共享内存连接到当前进程中的地址位置。它通常

是一个空指针,表示让系统来选择共享内存出现的地址。

shmflg是一组位标志。

25、shmdt()

头文件:#include <sys/ipc.h>

    #include <sys/shm.h>

函数原型:int shmdt(const void *shmaddr);

函数说明:shmdt函数的作用是将共享内存从当前进程中分离。

26、shmctl()

头文件:#include <sys/ipc.h>

    #include <sys/shm.h>

   函数原型:int shmctl(int shmid, int cmd, struct shmid_ds    *buf);

函数说明:该函数是共享内存的控制函数shmid是shmget返回的 共享内存标识符。cmd是要采取的动作,有三个取值。

27、msgget()

头文件:#include <sys/types.h>

  #include <sys/ipc.h>

  #include <sys/msg.h>

函数原型:int msgget(key_t key, int msgflg);

函数说明:msgget函数的作用是创建和访问一个消息队列。key 用来命名某个特定的消息队列。msgflg由9个权限标志组成。

28、msgsnd()

头文件:#include <sys/types.h>

  #include <sys/ipc.h>

     #include <sys/msg.h>

函数原型:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

函数说明:msgsnd函数用来把消息添加到消息队列中。

29、msgrcv()

头文件:#include <sys/types.h>

  #include <sys/ipc.h>

     #include <sys/msg.h>

函数原型:ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

函数说明:msgrcv函数从一个消息队列中获取消息。

30、msgctl()

头文件:#include <sys/types.h>

  #include <sys/ipc.h>

     #include <sys/msg.h>

函数原型:int msgctl(int msqid, int cmd, struct msqid_ds * buf);

函数说明:msgctl函数的作用与共享内存的控制函数非常类似。

31、pthread_create()

头文件:include <pthread.h>

函数原型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void*), void *arg);

函数说明:thread指向一个pthread_t型变量,用于返回线程ID。

attr:用于定制各种不同的线程属性,一般设为NULL。

start_routine:新线程的工作函数。

arg:传递给执行函数的参数。

32、pthread_self()

头文件:#include <pthread.h>

函数原型:pthread_t pthread_self(void);

函数说明:线程ID的获取方式有两种:通过pthread_create()返 回给调用者;通过pthread_self()获得其自身的ID。

33、pthread_equal()

头文件:#include <pthread.h>

函数原型:int pthread_equal(pthread_t t1, pthread_t t2);

函数说明:可以使用pthread_equal()函数检查两个线程ID是否  相同

34、pthread_exit()

头文件:#include <pthread.h>

函数原型:void pthread_exit(void *value_ptr);

函数说明:调用pthread_exit()等价于在工作函数中执行 return,区别是pthread_exit()可以在工作函数调用的任何函数 中被调用。

35、pthread_join()

头文件:#include <pthread.h>

函数原型:int pthread_join(pthread_t thread, void  **value_ptr);

返回值:成功返回0。

36、pthread_detach()

头文件:#include <pthread.h>

函数原型:int pthread_detach(pthread_t thread);

函数说明:线程分离。

Linux API查询

阅读数 1389