linux笔记1

IO重定向
作者 codercjg31 七月 2015, 3:22 下午

FILE*指针stdin、stdout和stderr连接在终端tty上,一般从键盘读取数据输入并把输出和错误消息写到屏幕。
stdin、stdout和stderr对应的文件描述符分别为0、1、2,可以把0、1、2连接到其他文件描述符,实现IO重定向。
有一个重要的原则:
当进程向内核申请文件描述符时,内核始终为进程分配最低可用文件描述符
方法1:close then open

include <stdio.h>

include <fcntl.h>

void
main()

{

char
line[100];

int
fd;

fgets
(line, 100, stdin);

fputs
(line, stdout);

close(0);

fd = open(
"/etc/passwd"
, O_RDONLY);

if
(fd != 0)

{

printf
(
"error: %d\n"
, fd);

exit
(0);

}

fgets
(line, 100, stdin);

fputs
(line, stdout);

}

方法2:open…close…dup…close****方法3:open..dup2…close
<pre>#include <stdio.h>

include <fcntl.h>

void
main()

{

char
line[100];

int
fd;

fgets
(line, 100, stdin);

fputs
(line, stdout);

fd = open(
"/etc/passwd"
, O_RDONLY);

// close(0);

// dup(fd);

dup2(fd, 0);

close(fd);

fgets
(line, 100, stdin);

fputs
(line, stdout);

}

其实本质就是先关闭文件描述符0和tty输入(键盘)的连接,然后把0和要重定向的文件建立连接,
这个是通过内核始终为进程分配最低可用文件描述符这个特点实现的。

分类: Linux | 评论

信号驱动IO
作者 codercjg30 七月 2015, 5:24 下午

信号驱动IO, 是指当文件或设备可读或可写时,内核发送信号SIGIO给进程,通知进程进行相应的读或写操作。
相关操作分三步:
1.signal()设置SIGIO信号处理函数
2.fcntl()设置SIGIO信号要发送的进程
3.fcntl()设置IO为O_ASYNC,设置文件或设备可读或可写时,内核发送信号给进程
例子:

include <stdio.h>

include <stdlib.h>

include <signal.h>

include <fcntl.h>

include <curses.h>

int
over = 0;

void
signal_hanlder(
int
signo)

{

char
ch;

if
(signo == SIGIO)

{

fscanf
(stdin,
"%c"
, &ch);

fprintf
(stdout,
"input: %c\r\n"
, ch);

fflush
(stdout);

if
(ch ==
'Q'
)

{

over = 1;

endwin();

exit
(0);

}

}

}

void
main(
void
)

{

int
flag;

initscr();

signal
(SIGIO, signal_hanlder);

fcntl(0, F_SETOWN, getpid());

flag = fcntl(0, F_GETFL);

flag |= O_ASYNC;

fcntl(0, F_SETFL, flag);

while
(over == 0);

endwin();

}
setvbuf()设置流的缓冲区
作者 codercjg24 七月 2015, 3:14 下午

setvbuf
用 法: *int setvbuf(FILE *stream, char buf, int type, unsigned size);
type : 期望缓冲区的类型:
_IOFBF(满缓冲):当缓冲区为空时,从流读入数据。或者当缓冲区满时,向流写入数 据。
_IOLBF(行缓冲):每次从流中读入一行数据或向流中写入一行数据。
_IONBF(无缓冲):直接从流中读入数据或直接向流中写入数据,而没有缓冲区。
size : 缓冲区内字节的数量。
注意:This function should be called once the file associated with the stream has already been opened but before any input or output operation has taken place.
意思是这个函数应该在打开流后,立即调用,在任何对该流做输入输出前

例子:

include <stdio.h>

define BUF_SIZE 4

char
buf[BUF_SIZE];

void
main(
void
)

{

//setvbuf(stdout, buf, _IOFBF, BUF_SIZE);

//setvbuf(stdout, buf, _IONBF, BUF_SIZE);

setvbuf
(stdout, NULL, _IOLBF, 0);

fputs
(
"11"
, stdout);

fputs
(
"22"
, stdout);

fputs
(
"\n"
, stdout);

fputs
(
"33"
, stdout);

fputs
(
"44"
, stdout);

fputs
(
"55"
, stdout);

fputs
(
"\n"
, stdout);

fputs
(
"66"
, stdout);

fputs
(
"\n"
, stdout);

}

分类: Linux | 评论

getopt()获取命令行参数
作者 codercjg24 七月 2015, 3:00 下午

getopt()用于从命令行获取参数,声明如下:

include ;

*int getopt(int argc, char * const argv[], const char optstring);
extern char *optarg;
extern int optind, opterr, optopt;
该函数的argc和argv参数通常直接从main()的参数直接传递而来。optstring是选项字母组成的字串。
如果该字串里的任一字符后面有一个冒号,那么这个选项就要求有参数,选项和参数之间用空格隔开,如gcc main.c -o main。
如果该字串里的任一字符后面有两个冒号,那么这个选项就要求有参数,选项之后就是参数, 如gcc main.c -o main -lpthread。

当给定getopt()命令参数的数量 (argc)、指向这些参数的数组 (argv) 和选项字串 (optstring) 后,getopt() 将返回第一个选项,并设置一些全局变量。使用相同的参数再次调用该函数时,它将返回下一个选项,并设置相应的全局变量。如果不再有可识别的选项,将返回 -1,此任务就完成了。
getopt() 所设置的全局变量包括:
char *optarg——当前选项参数字串(如果有)。
int optind——argv的当前索引值。当getopt()在while循环中使用时,循环结束后,剩下的字串视为操作数,在argv[optind]至argv[argc-1]中可以找到。
int opterr——这个变量非零时,getopt()函数为“无效选项”和“缺少参数选项,并输出其错误信息。
int optopt——当发现无效选项字符之时,getopt()函数或返回’?'字符,或返回’:'字符,并且optopt包含了所发现的无效选项字符。

例子如下:

include <unistd.h>;

include <stdio.h>;

void
main(
int
argc,
char
*argv[])

{

int
oc;

while
((oc=getopt(argc, argv,
"ab:c::"
))!=-1)

{

switch
(oc)

{

case
'a'
:

printf
(
"get a\n"
);

break
;

case
'b'
:

printf
(
"%s\n"
, optarg);

break
;

case
'c'
:

printf
(
"%s\n"
, optarg);

break
;

case
'?'
:

printf
(
"no argument\n"
);

break
;

default
:

printf
(
"usage error\n"
);

break
;

}

}

}

分类: Linux | 评论

select()用法
作者 codercjg21 七月 2015, 3:32 下午

select()的功能是使进程阻塞一定时间,直到监视的文件描述符集合中有描述符可读、可写或出错。
函数原型:
int
select(
int
nfds,
struct
fd_set readfds,
struct
fd_set writefds,
struct
fd_set* exceptfds,
struct
timeval *timeout)

参数说明:
参数n为监视的最大文件描述符加1;
fd_set为文件描述符集合,下面的宏提供了处理这三种描述词组的方式:
FD_CLR(inr fd,fdset *set):用来清除描述词组set中相关fd 的位
FD_ISSET(int fd,fd_set *set):用来测试描述词组set中相关fd 的位是否为真
FD_SET(int fd,fd_set *set):用来设置描述词组set中相关fd的位:
FD_ZERO(fd_set *set):用来清除描述词组set的全部位
参数timeout为结构timeval,用来设置select()的等待时间,其结构定义如下:
struct
timeval{

timet tvsec;

timet tvusec;

};

1)如果timeout设为NULL,则表示select()一直阻塞,直到有描述符状态发生变化
2)如果timeout值为0,则select直接返回
3)如果timeout为某个特定值,则在特定时间内阻塞直到有描述符状态变化,如果这个时间内所有句柄状态都无变化,则select()超时返回0
返回值:
执行成功则返回文件描述词状态已改变的个数,如果返回0代表在描述词状态改变前已超过timeout时间;当有错误发生时则返回-1,错误原因存于errno
下面是一个用select()等待标准输入有数据的例子,标准输入的文件描述符为0, select()中参数n为0+1.

include <unistd.h>

include <sys/types.h>

include <sys/time.h>

include <stdio.h>

void
main(
void
)

{

fd_set inset;

struct
timeval timeout;

int
ret;

int
ch;

while
(1)

{

timeout.tv_sec = 2;

timeout.tv_usec = 0;

FD_ZERO(&inset);

FD_SET(0, &inset);

ret = select(0+1, &inset, NULL, NULL, &timeout);

if
(ret>0 && FD_ISSET(0, &inset))

{

ch =
getchar
();

printf
(
"%c\n"
, ch);

if
(ch ==
'q'
)

break
;

}
else
if
(ret==0)

{

printf
(
"time out\n"
);

}
else
{

printf
(
"error\n"
);

}

}

printf
(
"finish\n"
);

}

分类: Linux | 评论

linux线程实例
作者 codercjg20 七月 2015, 3:06 下午

线程用法:

include <unistd.h>

include <pthread.h>

include <stdio.h>

void

  • tfunc1(
    void
  • arg);

void

  • tfunc2(
    void
  • arg);

void
main(
void
)

{

pthread_t tid1, tid2;

void
*arg;

if
(pthread_create(&tid1, NULL, tfunc1, NULL))

{

printf
(
"create error\n"
);

}

printf
(
"child pid1 %lu\n"
, tid1);

sleep(1);

if
(pthread_create(&tid2, NULL, tfunc2, NULL))

{

printf
(
"create error\n"
);

}

if
(pthread_join(tid2,&arg))

{

printf
(
"join error\n"
);

}

printf
(
"return val:%d\n"
, *(
int
*)arg);

printf
(
"exit\n"
);

}

void

  • tfunc1(
    void
  • arg)

{

printf
(
"child thread \n"
);

pthread_exit(NULL);

}

int
a=1;

void

  • tfunc2(
    void
  • arg)

{

printf
(
"child thread \n"
);

sleep(5);

a = 2;

//pthread_exit(&a);

return
&a;

}

编译时要加上线程库 gcc -lpthread
互斥锁用法:

include <unistd.h>

include <pthread.h>

include <stdio.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int
a = 1;

void

  • thread1(
    void
  • arg)

{

pthread_mutex_lock(&mutex);

a++;

sleep(1);

a--;

pthread_mutex_unlock(&mutex);

return
NULL;

}

void

  • thread2(
    void
  • arg)

{

sleep(1);

pthread_mutex_lock(&mutex);

printf
(
"a: %d\n"
, a);

pthread_mutex_unlock(&mutex);

return
NULL;

}

void
main(
void
)

{

pthread_t tid1, tid2;

pthread_create(&tid1, NULL, thread1, NULL);

pthread_create(&tid2, NULL, thread2, NULL);

pthread_join(tid1, NULL);

pthread_join(tid2, NULL);

}

信号量用法:

include <unistd.h>

include <pthread.h>

include <stdio.h>

include <semaphore.h>

sem_t sem;

int
a = 1;

void

  • thread1(
    void
  • arg)

{

a++;

sleep(1);

a--;

sem_post(&sem);

return
NULL;

}

void

  • thread2(
    void
  • arg)

{

sleep(1);

sem_wait(&sem);

printf
(
"a: %d\n"
, a);

return
NULL;

}

void
main(
void
)

{

pthread_t tid1, tid2;

sem_init(&sem, 0, 0);

pthread_create(&tid1, NULL, thread1, NULL);

pthread_create(&tid2, NULL, thread2, NULL);

pthread_join(tid1, NULL);

pthread_join(tid2, NULL);

sem_destroy(&sem);

}

分类: Linux | 评论

Linux信号
作者 codercjg17 七月 2015, 11:27 上午

信号一般由一个进程发给另一个进程(或自己),也可以由内核发送给一个进程。
例子如下:

include <unistd.h>

include <sys/types.h>

include <signal.h>

static
void
signal_usr(
int
signal
)

{

if
(
signal
== SIGUSR1)

printf
(
"recv SIGUSR1\n"
);

else
if
(
signal
== SIGUSR2)

printf
(
"recv SIGUSR2\n"
);

else

printf
(
"recv unknown signal\n"
);

}

void
main()

{

if
(
signal
(SIGUSR1, signal_usr) == SIG_ERR)

printf
(
"can't catch SIGUSR1\n"
);

if
(
signal
(SIGUSR2, signal_usr) == SIG_ERR)

printf
(
"can't catch SIGUSR2\n"
);

while
(1)

pause();

}

SIGUSR1和SIGUSR2是用户自定义信号,通过ps -a命令可列出进程id为2913,通过kill -SIGUSR1 2913和kill -SIGUSR2 2913发送信号给该进程。
kill命令准确的说不是杀死对应的进程,而是向指定进程发送信号,而默认发送的信号是SIGTERM, 收到该信号后进程终止。

分类: Linux | 评论

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容