zoukankan      html  css  js  c++  java
  • exec函数族,守护进程,线程同步和互斥

    2015.3.2

    进程和程序有三点不同:
    1,存在位置不同,程序:硬盘,磁盘。进程:内存
    2. 程序是静态的,进程是动态的

    执行./a.out -->bash->bash程序调用fork()-->子进程将./a.out后面的参数存放到argv[].然后调用exec处理这些参数,最后子进程退出,光标闪动

    进程进入停止态:1,调试的时候,2,将前台变成后台运行

    线程:每个程序加载到内存后可以对应创建一个或多个顺序执行流(能使进程在同一时刻做不止一件事,每个线程处理各自独立的任务)

    回调函数

    同步和互斥

    exec函数族的基本用法参考:

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>

    void printUsage(const char *argv0)
    {
    fprintf(stderr,
    "Usage : %s <exec type> "
    "exec type : execl "
    " execlp, "
    " execv, "
    " execvp ",
    argv0);
    }

    int main(int argc, char *argv[])
    {
    char *vector[] = {"ps","-f",NULL};

    if(argc != 2)
    {
    printUsage(argv[0]);
    return 1;
    }

    if(0 == strcmp(argv[1],"execl"))
    {
    if(execl("/bin/ps","ps","-f",NULL) < 0)
    {
    perror("execl error!");
    }
    }

    else if(0 == strcmp(argv[1],"execlp"))
    {
    if(execlp("ps","ps","-f",NULL) < 0)
    {
    perror("execlp error!");
    }
    }

    else if(0 == strcmp(argv[1],"execv"))
    {
    if(execv("/bin/ps",vector) < 0)
    {
    perror("execv error!");
    }
    }

    else if(0 == strcmp(argv[1],"execvp"))
    {
    if(execvp("ps",vector) < 0)
    {
    perror("execvp error!");
    }
    }

    perror("note the program will not step the exec() function met some errors");

    return 0;
    }


    守护进程的创建和出错处理:(守护进程出错,将错误信息输出到文件中,调用日志函数实现)

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcnl.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>

    int main()
    {
    pid_t pid, sid;
    int i,fd;
    char *buf = "this is a Daemon ";

    pid = fork();

    if(pid < 0)
    {
    printf("error fork ");
    exit(1);
    }

    else if(pid > 0)
    {
    exit(0);
    }
    openlog("daemon_syslog",LOG_PID,LOD_DAEMON);

    if((sid = setsid()) < 0)
    {
    syslog(LOG_ERR,"%s ","setsid")
    exit(1);
    }

    if((sid = chdir("/")) < 0)
    {
    syslog(LOG_ERR,"%s ","setsid");
    exit(1);
    }

    for(i = 0; i < getdtablesize(); i++)
    {
    close(i);
    }

    while(1)
    {
    if((fd = open("/tmp/daemon.log",O_CREAT|OWRONLY|O_APPEND.0600))<0)
    {
    syslog(LOG_ERR,"open");
    exit(1);
    }

    write(fd,buf, strlen(buf) + 1);
    close(fd);
    sleep(10);
    }

    closelog();
    exit(0);
    }


    线程的创建,结束和回收!

    涉及到的相关函数如下:

    int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(start_continue)(void *),void *arg);
    void pthread_exit(void *retval);
    int pthread_join(pthread_t thread, void **thread_result);
    int pthread_cancle(pthread_t thread);

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

    char message[32] = "hello world";
    void *thread_function(void *arg);

    int main(int argc, char *argv[])
    {
    pthread_t a_thread;
    void *thread_result;

    if(pthread_create(&a_thread, NULL, thread_function,(void *)message) < 0)
    {
    perror("fail to pthread_create");
    exit(-1);
    }

    printf("waiting for thread to finish ");

    if(pthread_join(a_thread, &thread_result) < 0)
    {
    perror("fail to prhread_join");
    exit(-1);
    }

    printf("message is now %s ",message);

    return 0;
    }

    void *thread_function(void *arg)
    {
    printf("thread_function is runing,argument is %s ",(char *)arg);
    strcpy(message,"marked by thread");
    pthread_exit("thank you for the cpu time");
    }


    上面程序编译的时候用这条语句:gcc XXXX.c -lpthread -D _REENTRANT
    -lpthread // 链接pthread库
    -D _REENTRANT //生成可重入代码

    程序运行结果:
    lg@lg-desktop:/mnt/hgfs/source test/file IO$ gcc test13.c -lpthread -D_REENTRANT
    lg@lg-desktop:/mnt/hgfs/source test/file IO$ ./a.out
    waiting for thread to finish
    thread_function is runing,argument is hello world
    message is now marked by thread


    创建两个线程,分别执行不同的程序,最后退出并由主程序回收。

    #include <string.h>
    #include <pthread.h>

    char message1[] = "AAAAAAAAAA";
    char message2[] = "BBBBBBBBBB";
    void *thread_function1(void *arg1);
    void *thread_function2(void *arg2);


    int main(int argc, char *argv[])
    {
    pthread_t a_thread1,a_thread2;
    //void *thread_result;

    if(pthread_create(&a_thread1, NULL, thread_function1,(void *)message1) < 0)
    {
    perror("fail to pthread_create 1");
    exit(-1);
    }

    if(pthread_create(&a_thread2, NULL, thread_function2,(void *)message2) < 0)
    {
    perror("fail to pthread_create 2");
    exit(-1);
    }

    printf("waiting for thread to finish ");

    if(pthread_join(a_thread1, NULL) < 0)
    {
    perror("fail to prhread_join");
    exit(-1);
    }

    if(pthread_join(a_thread2,NULL) < 0)
    {
    perror("fail to prhread_join");
    exit(-1);
    }

    return 0;
    }

    void *thread_function1(void *arg1)
    {
    int i;
    for(i = 0; i < 3; i++)
    {
    printf("string is %s ",(void *)arg1);
    sleep(1);
    }

    pthread_exit("thread 1 is exit");
    }


    void *thread_function2(void *arg2)
    {
    int i;
    //sleep(10);
    for(i = 0; i < 3; i++)
    {
    printf("string is %s ",(void *)arg2);
    sleep(1);
    }

    pthread_exit("thread 2 is exit");
    }

    上面程序的运行结果:
    lg@lg-desktop:/mnt/hgfs/source test/file IO$ ./a.out
    waiting for thread to finish
    string is BBBBBBBBBB
    string is AAAAAAAAAA
    string is BBBBBBBBBB
    string is AAAAAAAAAA
    string is BBBBBBBBBB
    string is AAAAAAAAAA
    lg@lg-desktop:/mnt/hgfs/source test/file IO$


    线程间同步:
    信号量是一个受保护的量,只能通过三种操作进行访问:
    1.初始化
    2.P操作(申请资源)
    3.V操作(释放资源)

    信号量的值是非负整数

    p操作包含下面内容:

    if(信号量 > 0)
    {
    申请资源的任务继续运行;
    信号量的值 - 1;
    }
    else
    {
    申请资源的任务阻塞;
    }

    v操作包含下面的内容:

    if(没有任务在等待资源)
    {
    信号量的值 + 1;
    }
    else
    {
    唤醒第一个等待的任务,让其继续运行;
    }

    同步中涉及到的常用的信号量操作函数如下:

    int sem_init(sem_t *sem, int pshared, unsigned int value);
    int sem_wait(sem_t *sem);
    int sem_post(sem_t *sem);
    int sem_trywait(sem_t *sem);
    int sem_getvalue(sem_t *sem, int svalue);

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

    char buf[60];
    sem_t sem;
    void *function(void * arg);

    int main(int argc,char **argv)
    {
    pthread_t a_thread;
    void *thread_result;
    if(sem_init(&sem,0,0) < 0)
    {
    perror("fail to sem_init");
    exit(-1);
    }

    if(pthread_create(&a_thread,NULL,function,NULL) < 0)
    {
    perror("fail to pthread_create");
    exit(-1);
    }

    printf("input 'quit' to exit ");

    do
    {
    fgets(buf, 60, stdin);
    sem_post(&sem);
    }while(strncmp(buf,"quit",4) != 0);

    return 0;
    }

    void *function(void * arg)
    {
    while(1)
    {
    sem_wait(&sem);
    printf("you enter %d characters ",strlen(buf)-1);
    }
    }


    进程间互斥:加互斥锁

    互斥锁涉及到的一些常用函数如下:

    int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);
    int pthread_mutex_lock(pthread_mutex_t *mutex);
    int pthread_mutex_unlock(pthread_mutex_t *mutex);

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

    //#define _LOCK_

    unsigned int value1, value2,count;
    pthread_mutex_t mutex;
    void *function(void *arg);

    int main(int argc,char ** argv)
    {
    pthread_t a_thread;

    if(pthread_mutex_init(&mutex,NULL) < 0)
    {
    perror("fail to mutex_init");
    exit(-1);
    }

    if(pthread_create(&a_thread, NULL, function,NULL) < 0)
    {
    perror("fail to pthread_create");
    exit(-1);
    }

    while(1)
    {
    count++;
    #ifdef _LOCK_

    pthread_mutex_lock(&mutex);

    #endif

    value1 = count;
    value2 = count;

    #ifdef _LOCK_

    pthread_mutex_unlock(&mutex);

    #endif
    }

    return 0;
    }

    void *function(void *arg)
    {
    while(1)
    {

    #ifdef _LOCK_

    pthread_mutex_lock(&mutex);

    #endif

    if(value1 != value2)
    {
    printf("count = %d, value1 = %d, value2 = %d ",count, value1, value2);
    usleep(100000);
    }

    #ifdef _LOCK_

    pthread_mutex_unlock(&mutex);

    #endif
    }

    return NULL;
    }

    将define _LOCK_ 屏蔽后运行结果:(不屏蔽程序没有输出,value1和value2相等)
    lg@lg-desktop:/mnt/hgfs/source test/file IO$ gcc lock14.c -lpthread -D_REENTRANT
    lg@lg-desktop:/mnt/hgfs/source test/file IO$ ./a.out
    count = 3338702, value1 = 3338702, value2 = 3338701
    count = 53692966, value1 = 53692966, value2 = 53692965
    count = 89910265, value1 = 89910265, value2 = 89910264
    count = 125008213, value1 = 125008213, value2 = 125008212
    count = 149351134, value1 = 149351134, value2 = 149351133
    count = 171729575, value1 = 171729575, value2 = 171729574
    count = 228510044, value1 = 228510044, value2 = 228510043
    count = 256495259, value1 = 256495259, value2 = 256495258
    count = 287733530, value1 = 287733530, value2 = 287733529
    count = 324321776, value1 = 324321776, value2 = 324321775
    count = 365523395, value1 = 365523395, value2 = 365523394
    count = 420680808, value1 = 420680808, value2 = 420680807
    count = 448359597, value1 = 448359597, value2 = 448359596
    count = 494800004, value1 = 494800004, value2 = 494800003
    count = 528839826, value1 = 528839826, value2 = 528839825
    ^C
    lg@lg-desktop:/mnt/hgfs/source test/file IO$ ^C
    lg@lg-desktop:/mnt/hgfs/source test/file IO$

    互斥锁的另一个参考程序;

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

    #define THREAD_NUM 3
    #define REPEAT_NUM 3
    #define DELAY_TIME_LEVELS 3.0

    pthread_mutex_t mutex;

    void *thrd_func(void *arg)
    {
    int thrd_num = (int)arg;
    int delay_time = 0;
    int count = 0;
    int res;

    res = pthread_mutex_lock(&mutex);

    if(res)
    {

    printf("thread %d lock failed ",thrd_num);
    pthread_exit(NULL);
    }

    printf("thread %d is starting ",thrd_num);
    for(count = 0; count < REPEAT_NUM; count++)
    {
    delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;

    sleep(delay_time);
    printf(" Thread %d:job %d delay = %d ",
    thrd_num,count, delay_time);
    }

    printf("thread %d finished ",thrd_num);
    pthread_mutex_unlock(&mutex);

    pthread_exit(NULL);
    }

    int main(void)
    {
    pthread_t thread[THREAD_NUM];
    int no = 0, tpid;
    void *thrd_ret;

    srand(time(NULL));

    pthread_mutex_init(&mutex,NULL);

    for(no = 0; no < THREAD_NUM; no++)
    {
    tpid = pthread_create(&thread[no],NULL,thrd_func,(void *)no);
    if(tpid != 0)
    {
    printf("create thread %d failed ",no);
    exit(-1);
    }
    }

    printf("create treates success waiting for threads to finish... ");

    for(no = 0; no < THREAD_NUM; no++)
    {
    tpid = pthread_join(thread[no],&thrd_ret);
    if(tpid == 0)
    {
    printf("thread %d joined ",no);
    }
    else
    {
    printf("thread %d join failed ",no);
    }


    }
    pthread_mutex_destroy(&mutex);

    return 0;
    }

    上面程序运行结果:(结果和书本上有所不同,分析原因是线程执行顺序不同,但是第一个thread 2 is starting有疑问,应该是thread 0 is starting才对,有待解决)
    lg@lg-desktop:/mnt/hgfs/source test/file IO$ gcc thread_mutex.c -lpthread -D_REENTRANT
    thread_mutex.c: In function ‘thrd_func’:
    thread_mutex.c:14: warning: cast from pointer to integer of different size
    thread_mutex.c: In function ‘main’:
    thread_mutex.c:58: warning: cast to pointer from integer of different size
    lg@lg-desktop:/mnt/hgfs/source test/file IO$ ./a.out
    create treates success
    waiting for threads to finish...
    thread 2 is starting
    Thread 2:job 0 delay = 3
    Thread 2:job 1 delay = 3
    Thread 2:job 2 delay = 1
    thread 2 finished
    thread 1 is starting
    Thread 1:job 0 delay = 1
    Thread 1:job 1 delay = 1
    Thread 1:job 2 delay = 1
    thread 1 finished
    thread 0 is starting
    Thread 0:job 0 delay = 3
    Thread 0:job 1 delay = 3
    Thread 0:job 2 delay = 2
    thread 0 finished
    thread 0 joined
    thread 1 joined
    thread 2 joined
    lg@lg-desktop:/mnt/hgfs/source test/file IO$

    ***************************************************************************************************************************************************************
    ***************************************************************************************************************************************************************
    ***************************************************************************************************************************************************************
    ***************************************************************************************************************************************************************

  • 相关阅读:
    系统的访问
    tomcat 和 数据库的连接
    实体类编写规则
    webmagic 爬虫
    docker安装官方Redis镜像并启用密码认证
    解决Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. 问题
    Springboot配置druid报错Failed to bind properties under 'spring.datasource' to javax.sql.DataSource
    阿里云centos7.6搭建SVN远程仓库和Git远程仓库
    java 三大特性封装继承多态
    使用easyui tab需要注意的问题
  • 原文地址:https://www.cnblogs.com/cnlg/p/4309903.html
Copyright © 2011-2022 走看看