美文网首页
Linux-C起步

Linux-C起步

作者: hutou | 来源:发表于2018-01-25 10:14 被阅读17次

名称解释

  1. ANSI C
    C语言标准,为各种操作系统上的C程序提供可移植性的保证
  2. POSIX标准
    定义了兼容操作系统的C语言系统接口以及工具标准
  3. 库函数
    库函数完成常见的特定功能,被应用程序调用
  4. 系统调用
    系统调用函数与操作系统相关,不同的操作系统使用的系统调用可能不同。库函数中也可以使用系统调用

第一个程序

写一个程序first.c

#include <stdio.h>

int main(int argc,char **argv)
{
  printf("this is first proram.\n");
  return 0;
}

使用gcc进行编译,链接

$ gcc first.c

运行一下看结果

$ ./a.out

调用函数

写一个阶乘的函数factorial.c

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

int factorial(int n)
{
  if(n <= 1) return 1;
  else
    return factorial (n-1) * n;
}

写一个调用文件second.c

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

int factorial(int n);

int main(int argc, char **argv)
{
  int n;
  if(argc < 2){
    printf("Usage: %s \n", argv[0]);
    return -1;
  }else{
    n = atoi(argv[1]);
    printf("Factorial of %d is %d . \n",n,factorial(n));
    return 0;
  }
}

编译和调用方法

$ gcc -c factorial.c
$ gcc -c second.c
$ gcc -o second factorial.o second.o
$ ./second  6

Make工具的使用

刚才我们看到了,如果我们的程序有多个文件,我们需要编译,链接才能正常调用程序。这个过程是很繁琐的,我们可以使用make工具来解决这个问题。
make工具会调用makefile文件,我们先写一个makefile看看
Makefile

second : second.o factorial.o
        gcc -o second second.o factorial.o
second.o : second.c
        gcc -c second.c
factorial.o : factorial.c
        gcc -c factorial.c
clean :
        rm -f *.o
        rm -f second

如果发现make有如下错误:

Makefile:2: *** 遗漏分隔符 。 停止。

可能是执行文件开头使用了空格,应该使用TAB。

Makefile中的常用变量
$@--目标文件
$^--所有依赖的文件
@<--第一个依赖文件

main: main.o mytool1.o mytool2.o
        cc -o $@ $^
main.o: main.c mytool1.h mytool2.h
        cc -c $<
mytool1.o: mytool1.c mytool1.h
        cc -c $<
mytool2.o: mytool2.c mytool2.h
        cc -c $<

库文件的使用

上面的例子中我们使用了printf函数,这个函数的实现是在库文件中。我们连接自己的应用程序的时候,编译器会查找对应函数的连接位置,运行时在当前系统内存空间中查找该库函数在对应库文件中的位置。
Linux系统下有两种库文件:

  1. 静态库:.a为后缀,应用程序从静态库中复制函数到二进制文件中
  2. 共享库:.so为后缀,应用程序运行时将函数代码从共享库文件中读出,从而间接引用。

系统库的路径:

# 系统必备共享库
/lib
# 标准共享库和静态库
/usr/lib
# 本地函数库
/usr/local/lib

库文件的搜索路径为:

  1. 环境变量:LD_LIBRARY_PATH 所指定的位置
  2. 搜索动态加载器在/etc 目录下的缓存文件 /etc/ld.so.cache

在进行cc编译的时候,会自动链接一些常用的库,这就是为什么printf不需要指定链接库的原因。如果我们需要指定库的路径可以使用如下方法:

cc -o temp temp.c -L/home/hutou/myLib

系统缺省库位置:/lib,/usr/lib,/usr/local/lib

静态库的使用

  1. 创建静态库:主要使用ar命令
    创建hello.c,hello.h 文件
#ifndef _libhello_H_
#define _libhello_H_
void hello(void);

#endif
#include <stdio.h>
#include "hello.h"

void hello(void){
        printf("this is a static lib.\n");
}

编译生成静态库hello.a

$ gcc -c hello.c
$ ar rc hello.a hello.o
  1. 使用静态库
    使用静态库需要两个文件:头文件,静态库文件
    默认库文件如果不在库搜索路径中,需要将此库文件拷贝到当前目录,或者在编译时指定库文件路径
    书写一个调用静态库的文件 libuse.c
#include <stdio.h>
#include "hello.h"

int main(int argc, char **argv){
        hello();
        return 0;
}

编译链接

$ gcc -o useHello libuse.c hello.a 

共享库的使用

共享库的创建基本上与静态库相同,主要的差别体现在编译上

  1. 使用gcc和参数-fPIC将源代码编译成.o的目标代码
  2. 使用-shared来创建共享库

下面我们使用上面的hello.c,编译成共享库

# 生成.o的目标文件
gcc -fPIC -c hello.c
# 编译共享库,指定共享库名称和版本,-lc表示引用c库
 gcc -shared  -o libhello.so.1.0 hello.o -lc
# 创建软连接
ln -sf libhello.so.1.0 libhello.so

下面我们看看怎么使用共享库

# 编译程序,生成目标文件
gcc -c libuse.c -o libuse.o
# 连接程序,-L 表示查找库的路径
gcc -o useDynHello libuse.o -L ./ -lhello
# 通过ldd命令查看引用的动态库
ldd useDynHello
# 调用程序,需要指定共享库的位置
LD_LIBRARY_PATH=$(pwd) ./useDynHello

说明一下,还记得我们说过的库文件的搜索路径。我们在链接程序的时候,指定了 -L 的路径,如果将我们的共享库放置在可以搜索到的路径下,则不用指定此参数。

进程

程序:包含可执行代码的文件,是一个静态文件。
进程:一个开始执行但是还没有结束的程序实例。
程序被系统调入内存,系统给程序分配一定的资源,让程序变成进程,为了区分进程,系统会给每一个进程分配一个ID号。进程有新建,运行,阻塞,就绪,完成五个状态。

  1. 获得进程ID号
#include <unist.h>
pid_t getpid(void);  //  获得进程的ID
pid_t getppid(void);  //  获得父进程的ID

演示用程序

#include <unistd.h>
#include <stdio.h>
int main(int argc,char *argv){
        printf("process id = %d\n",getpid());
        printf("process parent id = %d\n", getppid());
}
  1. 运行中出现:段错误(吐核)
    使用如下的命令进行调试(pid是运行的程序)
strace ./pid
  1. 进程的所有者和执行者
#include <stdio.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
    printf("这是程序的运行者%d\n", getuid());
    printf("这是程序的所有者%d\n", geteuid());
    printf("这是组ID =%s\n", getgid());
    printf("这是组EID =%s\n", getegid());
    return 0;
}
  1. 登录用信息
#include <stdio.h>
#include <pwd.h>
int main(int argc, char const *argv[])
{
        struct passwd* my_info;
        my_info = getpwuid(getuid());

        if(my_info)
        {
                printf("我的登录名:%s\n", my_info->pw_name);
                printf("我的密码:%s\n", my_info->pw_passwd);
                printf("我的ID= %ld\n", my_info->pw_uid);
                printf("我的组ID= %ld\n", my_info->pw_gid );
                printf("我的真实名称:%s\n", my_info->pw_gecos);
                printf("我的Home目录:%s\n", my_info->pw_dir);
                printf("我的Sheel:%s\n", my_info->pw_shell);
        }
        return 0;
}

相关文章

  • Linux-C起步

    名称解释 ANSI CC语言标准,为各种操作系统上的C程序提供可移植性的保证 POSIX标准定义了兼容操作系统的C...

  • 迅为IMX6ULL开发板C程序调用shell

    本章节介绍的是在 linux 系统环境下 linux-C 调用 shell 命令控制GPIO输入输出步骤。shel...

  • Linux-c inotify监控目录和文件使用

    在Linux相关项目中,遇到过这样子的需求,要监控某个目录下文件的改动,比如新建,删除等,这时候inotify就派...

  • 起步是开始,好感是接触

    四词故事:起步、好感、价格、朋友 起步是开始,好感是接触,价格是尺度,朋友是用心 起步是开始 不要刚起步就想赚回钱...

  • 起步

    起步

  • 起步

    我奶初见我慌仗,蚊帐里面低头忙,口说贵人不敢看,其实那时街上忙。下了学后去工厂,二十二年在草莽。扛铁管子肩压疼,人...

  • 起步

    事情总有个开始,我一直想做一个好的物理老师。没想到孩子终于在小学六年级要毕业的时候,展现出了对物理的兴趣。而且他自...

  • 起步

    今天晚上,跟一位好哥哥聊了一会,他教我正确的人生观,价值观和学习观。

  • 起步

    棉燕,敏玲,敏旋,晓敏,柔燕……我们的现如今这个阶段都是相同的! 又开始绕道之前的话题了,相亲,事业。今天跟晓敏聊...

  • 起步

    我今天谈抄谈得比较多。越是起步的公司,对抄的依赖更大。因为别人已经折腾出了成功的模式,创新模式的代价太大了,新公司...

网友评论

      本文标题:Linux-C起步

      本文链接:https://www.haomeiwen.com/subject/wkucpttx.html