学习init所用到的C语言知识

  C语言库函数名: atoi
  功 能: 把字符串转换成整型数.
  名字来源:array to integer 的缩写.
  原型: int atoi(const char *nptr);
  函数说明: 参数nptr字符串,如果第一个非空格字符不存在或者不是数字也不是正负号则返回零,否则开始做类型转换,之后检测到非数字(包括结束符 \0) 字符时停止转换,返回整型数。
  头文件: #include <stdlib.h>
  程序例:
  1)
  #include <stdlib.h>
  #include <stdio.h>
  int main(void)
  {
  int n;
  char *str = "12345.67";
  n = atoi(str);
  printf("string = %s integer = %d\n", str, n);
  return 0;
  }
  执行结果
  string = 12345.67 integer = 12345

  2)  

  #include <stdlib.h>
  #include <stdio.h>
  int main()
  {
  char a[] = "-100" ;
  char b[] = "123" ;
  int c ;
  c = atoi( a ) + atoi( b ) ;
  printf("c = %d\n", c) ;
  return 0;
  }

  执行结果
  c = 23

  简单的实现atoi函数源代码:
  #include <cctype>
  int my_atoi(const char* p){
  assert(p != NULL);
  bool neg_flag = false;// 符号标记
  int res = 0;// 结果
  if(p[0] == '+' || p[0] == '-')
  neg_flag = (*p++ != '+');
  while(isdigit(*p)) res = res*10 + (*p++ - '0');
  return neg_flag ? -res : res;
  }

  C语言库函数名:strchr

  原型:extern char *strchr(const char *s,char c);

  const char *strchr(const char* _Str,int _Val)
  char *strchr(char* _Str,int _Ch)
  头文件:#include <string.h>
  功能:查找字符串s中首次出现字符c的位置
  说明:返回首次出现c的位置的指针,如果s中不存在c则返回NULL。
  返回值:Returns the address of the first occurrence of the character in the string if successful, or NULL otherwise
  举例1:(在Visual C++ 6.0中运行通过)
  #include <string.h>
  #include <stdio.h>
  int main(void)
  {
  char string[17];
  char *ptr, c = 'r';
  strcpy(string, "This is a string");
  ptr = strchr(string, c);
  if (ptr)
  printf("The character %c is at position: %d\n", c, ptr-string);
  else
  printf("The character was not found\n");
  return 0;
  }
  运行结果:The character r is at position: 12Press any key to continue
  举例2:
  // strchr.c
  #include <stdio.h>
  #include <string.h>
  int main()
  {
  char temp[32];
  memset(temp,0,sizeof(temp));
  strcpy(temp,"Golden Global View");
  char *s = temp;
  char *p,c='v';
  p=strchr(s,c);
  if(p)
  printf("%s",p);
  else
  printf("Not Found!");
  return 0;
  }
  运行结果:Not Found!Press any key to continue
  举例3:
  #include <stdio.h>
  #include <string.h>
  void main()
  {
  char answer[100],*p;
  printf("Type something:\n");
  fgets(answer,sizeof answer,stdin);
  if((p = strchr(answer,'\n')) != NULL)
  *p = '\0';
  printf("You typed \"%s\"\n",answer);
  }
  fgets不会像gets那样自动地去掉结尾的\n,所以程序中手动将\n位置处的值变为\0,代表输入的结束。
C语言函数名:mmap

mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。

用法

  #include <sys/mman.h>
  void *mmap(void *start, size_t length, int prot, int flags,
  int fd, off_t offset);
  int munmap(void *start, size_t length);

参数
  start:映射区的开始地址。
  length:映射区的长度。
  prot:期望的内存保护标志,不能与文件的打开模式冲突。是以下的某个值,可以通过or运算合理地组合在一起
  PROT_EXEC //页内容可以被执行
  PROT_READ //页内容可以被读取
  PROT_WRITE //页可以被写入
  PROT_NONE //页不可访问
  flags:指定映射对象的类型,映射选项和映射页是否可以共享。它的值可以是一个或者多个以下位的组合体
  MAP_FIXED //使用指定的映射起始地址,如果由start和len参数指定的内存区重叠于现存的映射空间,重叠部分将会被丢弃。如果指定的起始地址不可用,操作将会失败。并且起始地址必须落在页的边界上。
  MAP_SHARED //与其它所有映射这个对象的进程共享映射空间。对共享区的写入,相当于输出到文件。直到msync()或者munmap()被调用,文件实际上不会被更新。
  MAP_PRIVATE //建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件。这个标志和以上标志是互斥的,只能使用其中一个。
  MAP_DENYWRITE //这个标志被忽略。
  MAP_EXECUTABLE //同上
  MAP_NORESERVE //不要为这个映射保留交换空间。当交换空间被保留,对映射区修改的可能会得到保证。当交换空间不被保留,同时内存不足,对映射区的修改会引起段违例信号。
  MAP_LOCKED //锁定映射区的页面,从而防止页面被交换出内存。
  MAP_GROWSDOWN //用于堆栈,告诉内核VM系统,映射区可以向下扩展。
  MAP_ANONYMOUS //匿名映射,映射区不与任何文件关联。
  MAP_ANON //MAP_ANONYMOUS的别称,不再被使用。
  MAP_FILE //兼容标志,被忽略。
  MAP_32BIT //将映射区放在进程地址空间的低2GB,MAP_FIXED指定时会被忽略。当前这个标志只在x86-64平台上得到支持。
  MAP_POPULATE //为文件映射通过预读的方式准备好页表。随后对映射区的访问不会被页违例阻塞。
  MAP_NONBLOCK //仅和MAP_POPULATE一起使用时才有意义。不执行预读,只为已存在于内存中的页面建立页表入口。
  fd:有效的文件描述词。如果MAP_ANONYMOUS被设定,为了兼容问题,其值应为-1。
  offset:被映射对象内容的起点。
返回说明
  成功执行时,mmap()返回被映射区的指针,munmap()返回0。失败时,mmap()返回MAP_FAILED[其值为(void *)-1],munmap返回-1。errno被设为以下的某个值
  EACCES:访问出错
  EAGAIN:文件已被锁定,或者太多的内存已被锁定
  EBADF:fd不是有效的文件描述词
  EINVAL:一个或者多个参数无效
  ENFILE:已达到系统对打开文件的限制
  ENODEV:指定文件所在的文件系统不支持内存映射
  ENOMEM:内存不足,或者进程已超出最大内存映射数量
  EPERM:权能不足,操作不允许
  ETXTBSY:已写的方式打开文件,同时指定MAP_DENYWRITE标志
  SIGSEGV:试着向只读区写入
  SIGBUS:试着访问不属于进程的内存区
mmap设备操作
  mmap操作提供了一种机制,让用户程序直接访问设备内存,这种机制,相比较在用户空间和内核空间互相拷贝数据,效率更高。在要求高性能的应用中比较常用。mmap映射内存必须是页面大小的整数倍,面向流的设备不能进行mmap,mmap的实现和硬件有关。
编辑本段其他
  munmap执行相反的操作,删除特定地址区域的对象映射,基于文件的映射,在mmap和munmap执行过程的任何时刻,被映射文件的 st_atime可能被更新。如果st_atime字段在前述的情况下没有得到更新,首次对映射区的第一个页索引时会更新该字段的值。用 PROT_WRITE 和 MAP_SHARED标志建立起来的文件映射其st_ctime 和 st_mtime,在对映射区写入之后但在msync()通过MS_SYNC 和 MS_ASYNC两个标志调用之前会被更新

#define中的 #与##

#define GPEBLT_FUNCNAME(basename) (SCODE (GPE::*)(struct GPEBltParms *))&GPE::##basename
  在#define中,标准只定义了#和##两种操作。#用来把参数转换成字符串,##则用来连接两个前后两个参数,把它们变成一个字符串。
  

#include <stdio.h>
  #define paster( n ) printf( "token " #n" = %d\n ", token##n )
  int main()
  {
  int token9=10;
  paster(9);
  return 0;
  }

C语言库函数名:MEMCPY

概述

memcpy()函数可用来拷贝任意类型的数据

函数原型

#include <string.h>

void *memcpy(void *destination, void *source, unsigned int count);

详细描述

由source所指内存区域复制count个字符串到destination所指内存区域.

    * memcpy() 是用来做内存拷贝:
    * 可以用来拷贝任何数据类型的对象,而不像strcpy()函数那样仅限于字型.
    * 可以指定拷贝的数据长度.
    * source和destination所指内存区域不能重叠.
    * 如果不指定memcpy()函数要拷贝的字节数,函数将以null字符结束。因为并不是所有的数据都以null字符结束,所以最好为memcpy()函数指定要拷贝的字节数。
    * 如果拷贝不成功,函数返回NULL指针。所以在调用该函数时应该检测返回值是否为NULL再执行相应的操作。

返回值

若拷贝成功,函数返回指向destination的指针。 若拷贝不成功,函数返回NULL指针。

用法示例

   1 #include <stdio.h> 
   2 #include <string.h> 
   3 int main(void) 
   4 { 
   5    char source[] = "******************************";              //将sourse初始化为30个'*'
   6    char destination[] = "abcdefghijlkmnopqrstuvwxyz0123456709";   //给destination赋值
   7    char *ptr; 
   8    printf("destination before memcpy: %s\n", destination); 
   9    ptr = memcpy(destination, source, strlen(source)); 
  10    if (ptr)                                           //若拷贝成功,输出destination中的内容
  11       printf("destination after memcpy:  %s\n", destination); 
  12    else 
  13       printf("memcpy failed\n");                     //若拷贝不成功,输出错误信息
  14    return 0; 
  15 } 
       fork()函数 Linux
  #include<unistd.h>
  #include<sys/types.h>
  函数定义:
  pid_t fork( void);
  (pid_t 是一个宏定义,其实质是int 被定义在#include<sys/types.h>中)
  返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1
  函数说明:
  一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。
  子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间。
  linux将复制父进程的地址空间内容给子进程,因此,子进程有了独立的地址空间。
  为什么fork会返回两次?
  由于在复制时复制了父进程的堆栈段,所以两个进程都停留在fork函数中,等待返回。因为fork函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的。

调用fork之后,代码有两份,都从fork函数中返回,箭头表示各自的执行处
  示例代码:
  #include<sys/types.h> //对于此程序而言此头文件用不到
  #include<unistd.h>
  #include<stdio.h>
  int main(int argc, char ** argv )
  {
  int pid = fork();
  if (pid < 0) {
  // printf("error!");
  } else if( pid == 0 ) {
  // printf("This is the child process!");
  } else{
  // printf("This is the parent process! child process id = %d", pid);
  }
  return 0;
  }
  fork()系统在Linux中的返回值是没有NULL的.
  Error Codes
  出错返回错误信息如下:
  EAGAIN
  达到进程数上限.
  ENOMEM
  没有足够空间给一个新进程分配.
open(打开文件)
相关函数 read,write,fcntl,close,link,stat,umask,unlink,fopen
表头文件 #include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
定义函数 int open( const char * pathname, int flags);
int open( const char * pathname,int flags, mode_t mode);

函数说明 参数pathname 指向欲打开的文件路径字符串。下列是参数flags 所能使用的旗标:
O_RDONLY 以只读方式打开文件
O_WRONLY 以只写方式打开文件
O_RDWR 以可读写方式打开文件。上述三种旗标是互斥的,也就是不可同时使用,但可与下列的旗标利用OR(|)运算符组合。
O_CREAT 若欲打开的文件不存在则自动建立该文件。
O_EXCL 如果O_CREAT 也被设置,此指令会去检查文件是否存在。文件若不存在则建立该文件,否则将导致打开文件错误。此外,若O_CREAT与O_EXCL同时设置,并且欲打开的文件为符号连接,则会打开文件失败。
O_NOCTTY 如果欲打开的文件为终端机设备时,则不会将该终端机当成进程控制终端机。
O_TRUNC 若文件存在并且以可写的方式打开时,此旗标会令文件长度清为0,而原来存于该文件的资料也会消失。
O_APPEND 当读写文件时会从文件尾开始移动,也就是所写入的数据会以附加的方式加入到文件后面。
O_NONBLOCK 以不可阻断的方式打开文件,也就是无论有无数据读取或等待,都会立即返回进程之中。
O_NDELAY 同O_NONBLOCK。
O_SYNC 以同步的方式打开文件。
O_NOFOLLOW 如果参数pathname 所指的文件为一符号连接,则会令打开文件失败。
O_DIRECTORY 如果参数pathname 所指的文件并非为一目录,则会令打开文件失败。
此为Linux2.2以后特有的旗标,以避免一些系统安全问题。参数mode 则有下列数种组合,只有在建立新文件时才会生效,此外真正建文件时的权限会受到umask值所影响,因此该文件权限应该为(mode-umaks)。
S_IRWXU00700 权限,代表该文件所有者具有可读、可写及可执行的权限。
S_IRUSR 或S_IREAD,00400权限,代表该文件所有者具有可读取的权限。
S_IWUSR 或S_IWRITE,00200 权限,代表该文件所有者具有可写入的权限。
S_IXUSR 或S_IEXEC,00100 权限,代表该文件所有者具有可执行的权限。
S_IRWXG 00070权限,代表该文件用户组具有可读、可写及可执行的权限。
S_IRGRP 00040 权限,代表该文件用户组具有可读的权限。
S_IWGRP 00020权限,代表该文件用户组具有可写入的权限。
S_IXGRP 00010 权限,代表该文件用户组具有可执行的权限。
S_IRWXO 00007权限,代表其他用户具有可读、可写及可执行的权限。
S_IROTH 00004 权限,代表其他用户具有可读的权限
S_IWOTH 00002权限,代表其他用户具有可写入的权限。
S_IXOTH 00001 权限,代表其他用户具有可执行的权限。

返回值 若所有欲核查的权限都通过了检查则返回0 值,表示成功,只要有一个权限被禁止则返回-1。

错误代码 EEXIST 参数pathname 所指的文件已存在,却使用了O_CREAT和O_EXCL旗标。
EACCESS 参数pathname所指的文件不符合所要求测试的权限。
EROFS 欲测试写入权限的文件存在于只读文件系统内。
EFAULT 参数pathname指针超出可存取内存空间。
EINVAL 参数mode 不正确。
ENAMETOOLONG 参数pathname太长。
ENOTDIR 参数pathname不是目录。
ENOMEM 核心内存不足。
ELOOP 参数pathname有过多符号连接问题。
EIO I/O 存取错误。

附加说明 使用access()作用户认证方面的判断要特别小心,例如在access()后再作open()空文件可能会造成系统安全上的问题。

范例 #include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
main()
{
int fd,size;
char s [ ]=”Linux Programmer!\n”,buffer[80];
fd=open(“/tmp/temp”,O_WRONLY|O_CREAT);
write(fd,s,sizeof(s));
close(fd);
fd=open(“/tmp/temp”,O_RDONLY);
size=read(fd,buffer,sizeof(buffer));
close(fd);
printf(“%s”,buffer);
}

执行 Linux Programmer!

read(由已打开的文件读取数据)
相关函数 readdir,write,fcntl,close,lseek,readlink,fread
表头文件 #include<unistd.h>
定义函数 ssize_t read(int fd,void * buf ,size_t count);
函数说明 read()会把参数fd 所指的文件传送count个字节到buf指针所指的内存中。若参数count为0,则read()不会有作用并返回0。返回值为实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。

附加说明 如果顺利read()会返回实际读到的字节数,最好能将返回值与参数count 作比较,若返回的字节数比要求读取的字节数少,则有可能读到了文件尾、从管道(pipe)或终端机读取,或者是read()被信号中断了读取动作。当有错误发生时则返回-1,错误代码存入errno中,而文件读写位置则无法预期。

错误代码 EINTR 此调用被信号所中断。
EAGAIN 当使用不可阻断I/O 时(O_NONBLOCK),若无数据可读取则返回此值。
EBADF 参数fd 非有效的文件描述词,或该文件已关闭。

范例 参考open()。

sync(将缓冲区数据写回磁盘)
相关函数 fsync
表头文件 #include<unistd.h>
定义函数 int sync(void)
函数说明 sync()负责将系统缓冲区数据写回磁盘,以确保数据同步。
返回值 返回0。

write(将数据写入已打开的文件内)
相关函数 open,read,fcntl,close,lseek,sync,fsync,fwrite
表头文件 #include<unistd.h>
定义函数 ssize_t write (int fd,const void * buf,size_t count);
函数说明 write()会把参数buf所指的内存写入count个字节到参数fd所指的文件内。当然,文件读写位置也会随之移动。
返回值 如果顺利write()会返回实际写入的字节数。当有错误发生时则返回-1,错误代码存入errno中。
错误代码 EINTR 此调用被信号所中断。
EAGAIN 当使用不可阻断I/O 时(O_NONBLOCK),若无数据可读取则返回此值。
EADF 参数fd非有效的文件描述词,或该文件已关闭。
范例 请参考open()。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值