您的位置:首页 > 运维架构 > Linux

linux 系统编程学习笔记一

2012-12-05 21:29 495 查看
文件与i/o

汇编程序的hello world

.data #section

declaration

msg:

.ascii "hello world!\n" #our dear

string

len= . - msg #length of our

dear string

.text #section

declaration

#we must export the entry

point to the ELF linker or

.global _start #loader.they conventionally

recognize _start as their

#entry point. use ld -e foo to

override the default.

_start:

#write our string to stdout

movl $len,%edx #third argument:

message length

movl $msg,%etc #second argument:

pointer to message to write

movl $1,%ebx #first argument: file

handle(stdout)

movl $4,%eax #system call number

(sys_write)

int $0x80 #call kernel

#and exit

movl $0,%ebx #first argument:exit

code

movl $1,%eax #system call number

(sys_exit)

int $0x80 #call kernel

汇编:as -o hello.c hello.s

链接:ld -o hello hello.o

运行:./hello

以上代码等同于以下c代码:

#include <stdio.h>

char msg[14]="hello world!\n";

#define len 14

int main(void){

write(1,msg,len);

_exit(0);

}

c标准I/O与unbuffered I/O函数

c标准I/O用系统调用实现

fopen(3) 调用open打开文件,返回一个文件描述符,分配一个FILE结构体

fgetc(3) 通过传入的FILE参数,检查能否从I/O缓冲区读到下一个字符,如果

能就直接读,否则就调用read(2),把文件描述符传进去,让内核读取该文件

到I/O缓冲区

fputc(3) 同上,如果i/o缓冲区已满就调用write(2),把缓冲区内容写入文件

fclose(3) 如果缓冲区有未写入,则调用write(2)写回文件,然后调用close(2)关闭文

件,释放结构体和缓冲区

open\read\write\close等系统函数为无缓冲I/O(unbuffered I/O)

文件描述符:文件描述符表中的索引

每个进程linux内核都有一个task_struct结构体来维护进程相关信息,即进程描述符

(process descriptor) 或是进程控制块(pcb process control block)

task_struct中有一个指针指向files_struct结构体,称为文件描述符表

当调用open打开一个或创建一个新文件时,内核分配一个文件描述符返回给用户,

文件描述符表中的指针指向新打开文件

程序启动会打开三个文件:

标准输入stdtin 文件描述符为0

标准输出stdout 1

标准错误输出stderr 2

在头文件unistd.h中定义

#define STDIN_FILENO 0

#define STDOUT_FILENO 1

#define STDERR_FILENO 2

open/close

open打开或创建一个文件

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

/*返回新分配的文件描述符,出错返回-1*/

/*

pathname 文件名

flag常数值

必选项

O_RDONLY 只读

O_WRONLY 只写

O_RDWR 可读可写

可选项

O_APPEND 追加

O_CREAT 文件不存则创建

O_EXCL

O_TRUNC 如果文件已存在,且以只写或可读可写打开,则将其长度截断为0字节

*/

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

/*mode指定文件权限,可用八进制表示,0644表示-rw-r--r--

文件的权限由open的mode参数和当前进程的umask掩码决定

*/

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

close 关闭一个打开的文件

#include <stdio.h>

/*成功返回0

fd为文件描述符

*/

int close(int fd);

read/write

read 从打开的文件或设备中读取数据

#include <unistd.h>

/*成功返回字节数,出错返回顾-1,如果在调用前已到达文件末尾,返回0*/

/*count 表示请求读取的字节数

buf 数据保存缓冲区

ssize_t 表示有符号的size_t

*/

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

write 向打开的设备或文件中定数据

#include <unistd.h>

/*返回值通常等于count*/

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

示例代码:

从终端读数据再写回终端

#include <unistd.h>

#include <stdlib.h>

/*阻塞读终端*/

int main(void){

char buf[10];

int n;

n=read(STDIN_FILENO,buf,10);

if(n<0){

perror("read stdin_fileno");

exit(1);

}

write(STDOUT_FILENO,buf,n);

return 0;

}

运行结果:

yuezhenhua@ubuntu:/opt/sdk/tc$ gcc test40.c -o test40

yuezhenhua@ubuntu:/opt/sdk/tc$ ./test40

hello

hello

yuezhenhua@ubuntu:/opt/sdk/tc$ ./test40

hello world

hello worlyuezhenhua@ubuntu:/opt/sdk/tc$ d

d:找不到命令

执行过程:

shell进程创建test40进程,test40开始执行,shell进程睡眠等待test40退出

test40调用read时睡眠等待,直到终端设备输入换行符才从read返回,read只读取10个字符

剩余的字符仍然保存在内核的终端设备输入缓冲区中

test40进程打印并退出,这时shell进程恢复运行,从终端设备读取用户输入的命令

于是读走了终端设备输入缓冲区中剩余的字符d和换行符,把它当作一条命令解释执行

监视多个设备

while(1){

非阻塞read(设备一);

if(设备一有数据到达){

处理数据;

}

非阻塞read(设备二);

if(设备二有数据到达){

处理数据;

}

/*延迟一会儿再查询*/

sleep(n);

}

注:select(2)函数可以在阻塞的同时监视多个设备

#include <unistd.h>

#include <fcntl.h>

#include <errno.h>

#include <string.h>

#include <stdlib.h>

#define MSG_TRY "try again\n"

/*非阻塞读终端*/

int main(void){

char buf[10];

int fd,n;

fd=open("/dev/tty",O_RDONLY|O_NONBLOCK);

if(fd<0){

perror("open file /dev/tty");

exit(1);

}

tryagain:

n=read(fd,buf,10);

if(n<0){

if(errno==EAGAIN){

sleep(1);

write(STDOUT_FILENO,MSG_TRY,strlen(MSG_TRY));

goto tryagain;

}

perror("read /dev/tty");

exit(1);

}

write(STDOUT_FILENO,buf,n);

close(fd);

return 0;

}

#include <unistd.h>

#include <fcntl.h>

#include <errno.h>

#include <string.h>

#include <stdlib.h>

#define MSG_TRY "try again\n"

#define MSG_TIMEOUT "timeout\n"

/*非阻塞读终端和等待超时*/

int main(void){

char buf[10];

int fd,n,i;

fd=open("/dev/tty",O_RDONLY|O_NONBLOCK);

if(fd<0){

perror("open file /dev/tty");

exit(1);

}

for(i=0;i<5;i++){

n=read(fd,buf,10);

if(n>=0){

break;

}

if(errno!=EAGAIN){

perror("read /dev/tty");

exit(1);

}

sleep(1);

write(STDOUT_FILENO,MSG_TRY,strlen(MSG_TRY));

}

if(i==5){

write(STDOUT_FILENO,MSG_TIMEOUT,strlen(MSG_TIMEOUT));

}else{

write(STDOUT_FILENO,buf,10);

}

close(fd);

return 10;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: