一些LinuxC的小知识点(二)

一、read系统调用

      系统调用read的作用是:从与文件描述符filedes相关联的文件里读入nbytes个字节的数据,并把它们放到数据区buf中。它返回实际读入的字节数。这可能会小于请求的字节数。如果read调用返回0,就表述未读入任何数据,已经达到了文件尾。同样,如果返回的是-1,就表示read调用出现了错误。

#include <unistd>
size_t read(int filedes,void *buf,size_t nbytes);

二、普通文件(file)和设备文件(device)的区别

普通文件,即常用的磁盘文件由字节组成,磁盘文件中的字节数就是文件大小。而设备文件是链接,不是容器。键盘和鼠标不存储点击数:)设备文件的i节点存储 的是指向内核的子程序的指针,而不是文件的大小和存储列表。内核中传输设备数据的子程序被称为设备驱动程序。

三、在代码中控制控制台颜色

为了更方便地一眼看出程序输出的信息,很多时候我们都想要用颜色让输出的结果更为直观,无奈Linux下的颜色永远都是黑底绿字。其实改变颜色的方式很简单。如下代码所示

#include <stdio.h>
#include <stdlib.h>
#include "include/consoleColor.h"
int main(int argc, char *argv[])
{
    printf(color_Red);//红色
    printf("Hello, world!\n");
    printf(color_Green);//恢复成默认的绿色
    return EXIT_SUCCESS;
}

输出的效果:

需要include的头文件

#ifndef __CONSOLE_COLOR__
#define __CONSOLE_COLOR__
char * color_Black= "\x1b[01;30m";
char * color_Red= "\x1b[01;31m";
char * color_Green= "\x1b[01;32m";
char * color_Yellow= "\x1b[01;33m";
char * color_Blue= "\x1b[01;34m";
char * color_PurplishRed= "\x1b[01;35m";
char * color_Cyan= "\x1b[01;36m";
char * color_white= "\x1b[01;37m";
#endif

相关阅读:让你的linux虚拟终端五彩缤纷(1)——LS颜色设置

四、多线程程序makefile编写的注意事项

对于多线程makefile中,要注意添加-lpthread,以便添加pthread的链接库。另外,需要加入宏定义-D_REENTRANT,以便将有的不可充入的函数或者变量,变成可重入的,以便适应多线程的要求(详见图1)。

                                                                     图1 为什么添加-lpthread和_REENTERANT

下面是一个多线程的makefile。其中在ihome_arm.c这个文件中,我们用到了多线程。在ihome_arm.c中我们需要引用comtest.c中的函数。

ihome_arm : comtest.o ihome_arm.o
    arm

-linux-gcc -o ihome_arm comtest.o ihome_arm.o -L/usr/include/nptl -

lpthread
all: pthread
comtest.o : comtest.c
    arm

-linux-gcc -

c comtest.c
ihome_arm.o : ihome_arm.c comtest.c
    arm

-linux-gcc -D_REENTRANT -I/usr/include/nptl -

c ihome_arm.c
clean :
    

rm ihome_arm comtest.o ihome_arm.o

值得注意的是:在上面代码段中灰色背景下的语句前都要添加一个tab分隔符,必须是tab分隔符,不然就会报“Makefile:3:***遗漏分隔符。停止 。”。因为makefile中规定,如果是bash语句,那么必须在语句的最前用tab作分隔符。其中关于

-L/usr/include/nptl 的说明见图2.

 

                                                                         图2 为什么添加-L/usr/include/nptl

以上图片来自《Linux程序设计 第四版》

 

五、头文件和源文件引用的注意事项

知识点四中,我们程序里面有comtest.c、comtest.h、ihome_arm.c。其中在ihome_arm.c这个文件中,我们用到了多线程。在ihome_arm.c中我们需要引用comtest.c中的函数。我曾很傻气地直接在ihome_arm.c中直接引用comtest.c,结果导致大量的重复定义出现。正确的方式应该是,为ihome_arm.c引用的类型、变量、函数写一个comtest.h的头文件,这样就不会引起大量的重复定义。头文件编写的注意事项见上一篇文章。

 

六、Linux的sleep()和usleep()的使用和区别

1、sleep函数

函数名: sleep 
头文件: #include <windows.h> // 在VC中使用带上头文件 
             #include <unistd.h>    // 在gcc编译器中,使用的头文件因gcc版本的不同而不同 
功  能 : 执行挂起指定的秒数 
语  法 : unsigned sleep(unsigned seconds);

示例:

#include <unist.h>
 #include<stdio.h>
 int main()
 {
       int a;
       a=1;
       printf("hello");
       sleep(a);
       printf("world");
       return 0;
 }

2、usleep函数

函数名: usleep 
头文件: #include <unistd.h> 
功  能:  usleep功能把进程挂起一段时间, 单位是微秒(百万分之一秒); 
语  法:  void usleep(int micro_seconds); 
返回值: 无

内容说明:本函数可暂时使程序停止执行。参数 micro_seconds 为要暂停的微秒数(us)。 
 注 意: 
这个函数不能工作在windows 操作系统中。用在Linux的测试环境下面。 
参 见:usleep() 与sleep()类似,用于延迟挂起进程。进程被挂起放到reday queue。一般情况下,延迟时间数量级是秒的时候,尽可能使用sleep()函数。如果延迟时间为几十毫秒(1ms = 1000us),或者更小,尽可能使用usleep()函数。这样才能最佳的利用CPU时间。

七、时钟换算:

 微秒,时间单位,符号us(英语:microsecond ). 
1微秒等于百万分之一(10的负6 次方秒) 
0.000 001 微秒 = 1皮秒 
0.001 微秒 = 1纳秒 
1,000 微秒 = 1毫秒 
1,000,000 微秒 = 1秒 
1= 1000ms 
1ms = 1000μs 
1μs = 1000ns 
1ns = 1000ps 
1秒(s) = 1000 毫秒(ms) = 1,000,000 微秒(μs) = 1,000,000,000 纳秒(ns) = 1,000,000,000,000 皮秒(ps)

八、利用man查找制定C语言函数

man 3  函数

其中3代表man要查找的是C库函数。参考链接

九、多线程编程中主线程等待子进程结束

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

//省略了必要的函数
int main ( int argc, char **argv )
{
    struct MainArgus mMainArgus;
    mMainArgus.argc=argc;
    mMainArgus.argv=argv;
    int res;//用来判断线程是否创建成功,是否退出的标志
    pthread_t a_thread;
    void *thread_result;
    res = pthread_create ( &a_thread,NULL,uart_pthread, ( void * ) ( &mMainArgus ) );
    if ( res!=0 )
    {
        exit ( EXIT_FAILURE );
    }
    res

=pthread_join ( a_thread,&

thread_result );

    if ( res!=0 )
    {
        exit ( EXIT_FAILURE );
    }
    return EXIT_SUCCESS;
}

      在代码段中的灰色背景代码中,这句话关系到子线程a_thread能不能正常地运行完,pthread_join让main所在的主线程等待a_thread线程结束,才继续从pthread_join语句中往下执行。如果没有这一句,当子线程是比较耗时的操作,它在主线程运行到return EXIT_SUCCESS;的时候还没有结束的话,那么随着main所在的主线程的退出,子线程a_thread也将退出,也就是a_thread不能被正确地执行完,而是意外地退出了。 
     我们给pthread_join传递了两个参数,一个正在等待器结束的线程的标识符athread,另一个是指向线程返回值的指针。这个函数将等到它所指定的线程终止后才返回。然后main函数在pthread_join行之后,继续执行。

十、errno的由来

errno定义在头文件<errno,h>中,他是一个整形的变量。当系统调用和其他库函数发送错误的时候,errno用来标识错误是什么。

常用的用来报告错误的函数。它们是strerrorperror

1、strerror用来将错误代码errno映射成一个字符串,该字符串对发生的错误类型进行说明。

函数原型如下

#include <string.h>

char *strerror(int errnum);

char *strerror_r(int errnum, char *buf, size_t buflen);

2、perror用来把errno变量中报告的当前错误映射到一个字符串,并把它输出到标准错误输出流。该字符串的前面先加上字符串s(如果不为空)中给出的信息,在加上一个冒号和一个空格。

函数原型如下

#include <stdio.h>
void perror(const char *s);

3、一个小样例。在下面的这个例子中,我们错误地打开一个不存在的文件,产生一个errno,并用strerror和perror进行报告。

#include <stdio.h> //为了使用perror
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h> //为了使用errno
#include <string.h>//为了使用strerror
int main ( int argc, char *argv[] )
{
    int CommFd = open ( "/dev/kkk", O_RDWR, 0 );//这里故意打开一个错误的设备,以便引发一个错误
    if ( CommFd==-1 )
    {
        int errnosv=errno;
        perror ( "HelloError" );
        printf ( strerror ( errnosv ) );
    }
    printf ( "\n" );
    return EXIT_SUCCESS;
}

 

输出的结果如下:

十一、正确使用errno

一个常见的错误用法如下所示:

if (somecall() == -1) {
        printf("somecall() failed\n");
        if (errno == ...) { ... }
    }

当somecall引发了一个错误,errno被赋上值之后。你不应该直接使用errno进行其他的操作,在以上代码段中,errno可能被printf函数改变。如果我们要使用errno,最好的办法就是如下代码段所示的,把它保存在一个变量中,然后再使用。

if (somecall() == -1) {
        int errsv = errno;
        printf("somecall() failed\n");
        if (errsv == ...) { ... }
    }

十二、extern关键字的使用

首先注意,extern关键字不是用来声明全局变量的。下面看一段错误的代码

//假设这是一个头文件MyCode.h
extern char something[255];

然后我们想要在下面的源文件中引用something。

//MyCode.c
#include <stdlib.h>
#include <string.h>
#include <MyCode.h>
int main(){
   strcpy(something,"Hello world");//在这个地方编译器会爆出something没有定义(undefined错误)
   printf(something);
}

因为extern不是这么用的。extern的出现是为了解决源文件中的东西,不能被其他源文件访问的问题。一般来说,假设我们要访问一个源文件(假设是源文件myCode.c)中的变量,那么我们需要先在源文件MyCode.c中定义一个变量,通常是在所有函数的开头。然后在这个源文件对应的头文件MyCode.h中用extern标志这个变量,那么当其他源文件MyCodeTwo.c引用了头文件MyCode,h的时候,就可以访问到MyCode.c中定义的变量。如下代码段所示。

//MyCode.c修改后
#include <stdlib.h>
#include <string.h>
#include <MyCode.h>

int main(){
   strcpy(something,"Hello world");
   printf(something);
}

//MyCodeTwo.c
#include <stdlib.h>
#include <string.h>
#include <MyCode.h>
int main(){
   strcpy(something,"Hello world");//可以访问到MyCode.c的something
   printf(something);
}

十三、Tar打包、压缩与解压缩到指定目录的方法

tar在linux上是常用的打包、压缩、加压缩工具,他的参数很多,这里仅仅列举常用的压缩与解压缩参数。

1、将整个/home/www/images 目录下的文件全部打包为 /home/www/images.tar

tar -cvf /home/www/images.tar /home/www/images ← 仅打包,不压缩

tar -zcvf /home/www/images.tar.gz /home/www/images ← 打包后,以gzip压缩

在参数f后面的压缩文件名是自己取的,习惯上用tar来做,如果加z参数,则以tar.gz 或tgz来代表gzip压缩过的tar file文件

2、将 /home/www/images.tar.gz 解压到/home/www下面

cd /home/www

tar -zxvf /home/images.tar.gz

解压到指定的目录

tar -zxvf /home/images.tar.gz -C /specific dir

解包到指定的目录

tar xvf filename.tar -C /specific dir

作者:kissazi2 
出处:http://www.cnblogs.com/kissazi2/ 
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载:http://www.cnblogs.com/kissazi2/p/3148053.html

时间: 2024-11-08 19:05:06

一些LinuxC的小知识点(二)的相关文章

一些LinuxC的小知识点(一)

以下代码在Federo9上试验成功.   一.格式化输入16进制字符串 printf("Format:%.2x\n",10); 输入结果:   二.测试各类型的占用的字节数 int main(int argc, char *argv[]) { int OutputHex = 1; unsigned char aValue=10; char Buffer[10]; int len=sprintf(Buffer, OutputHex ? "%.2X " : "

jquery-jQuery一个小知识点,求教

问题描述 jQuery一个小知识点,求教 本来不想麻烦大神的,今天看视频教程$().ready(function(){ }); 和$(document).ready(function(){ });我百度了没有明确结果,希望比较懂Js的大神告诉我一声,这两个是不是一样的 解决方案 两者效果是一样的,当没有写document的时候,默认就是选中document$().ready(function () { } )与javascript中的onload=function ( ){ };效果也是一样的

微信小店二次开发功能套餐列表

本商品包括微信小店二次功能开发套餐.   [商品介绍]以下费用均为一次性费用.永久使用.   套餐一: 800元 订单查询:用户查询自己最近30天之内的订单记录.实时通知:用户付款成功后,实时通知用户订单详情.快递查询:已发货的订单,可以查询快递进度. 套餐二: 1200元 订单查询:用户查询自己最近30天之内的订单记录.实时通知:用户付款成功后,实时通知用户订单详情.快递查询:已发货的订单,可以查询快递进度.工作人员提醒:指定工作人员可以收到最新的订单通知. 套餐一和套餐二区别在于管理员微信提

ListView小知识点及技巧

小知识点: ListView添加header以后.ListView中的item的position变为从1开始而不再是从0开始. 需求描述: ListView原本有数据.先将ListView滑动到底部,再重新加载数据.加载完成后显示ListView的头部而不是仍然在底部 解决办法: adapter.notifyDataSetChanged(); listView.setAdapter(adapter);  

(杂)小知识点

以后的小知识点都保存在这里 ComponentName            public void onClick(View v) {  //组件名称,第一个参数是包名,也是主配置文件Manifest里设置好的包名  第二个是类名,要带上包名                      ComponentName com = new ComponentName("com.dujin", "com.djy.dudu");                  Intent

微信公众平台上线小程序二维码,便于商户线下推广

12月30日,微信公众平台上线小程序二维码,便于商户线下推广.开发者首先可在"设置"中查看小程序的正式二维码,该二维码只用于访问小程序的线上正式版本.然后,通过接口获得带参数二维码,最多可生成带参数二维码10000个.张小龙对外全面解释了外界所关注的,与"小程序"相关的九大问题.没有入口,启动来自扫描二维码:没有下载过程和应用商店.为了避免骚扰用户,"小程序"也不会有订阅关系.不能推送消息.不能推送到朋友圈,不能做游戏,它将提供有限的搜索能力,并

Java中的小知识点总结

最近在复习Java的基础,遇到了一些比较偏的考核题目,特地总结一下需要注意的知识点!不过在使用IDE编程的时候,这些问题都会马上被IDE识别出来,编译是通不过的.我在这里提出来就相当于给初学者一些贡献吧   一.声明局部变量是的一些特性和规则(1)声明的局部变量是不会被默认初始化的,成员变量则是会被默认初始化的.例如: 复制代码 代码如下: class Demo {         public static void main(String[] args) {            Strin

除了像菊花的微信小程序二维码,我还找到更多奇葩

   审美这事,萝卜青菜各有所爱.比如最近微信发布的小程序码,有人感慨"终于换掉了丑陋的二维码",有人却说它像"菊花". 微信推出小程序,是因为二维码丑吗?我觉得未必. 先来看看二维码是不是真的丑.这是罗辑思维家的动态二维码,丑吗? 这是专业设计师做出来的二维码,丑吗? [设计师:月儿妆] 在脑洞大开的设计师手里,二维码们并不甘为一个普通的二维码,它们个个都是有理想有追求的二维码.它可能想变成一个披萨: [设计师:dgnotdog] 或者变成一个科幻基地: [设计师

ACCESS数据库向MySQL快速迁移小程序(二)

access|mysql|程序|数据|数据库 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 以下为 import.php 源程序 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <html> <head> <style type=text/css> body,td,li,div,p,pre,a,b,h1,h2,h3,h4 {font-family:verdana;font-size:9pt;lin