免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5408 | 回复: 5
打印 上一主题 下一主题

关于多线程fork()文件描述符复制问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-16 17:25 |只看该作者 |倒序浏览
20可用积分
最近遇到一个问题, 很郁闷.
----------------------------

一个程序有A, B两个线程.

A线程会执行fork()操作, B线程会打开比较多的文件(fopen).

请问:B线程打开的文件描述符会被A线程的fork复制吗 ?


我使用的操作系统是solaris5.8, 线程库是POSIX Threads.


我man了fork看到了这2段话, 好象不会复制的意思.请大虾解答, 谢谢!

  Solaris Threads
     In applications that use the Solaris threads API rather than
     the POSIX threads API (applications linked with -lthread but
     not -lpthread),fork() duplicates in the  child  process  all
     threads  (see  thr_create(3THR)) and LWPs in the parent pro-
     cess. The  fork1()  function  duplicates  only  the  calling
     thread (LWP) in the child process.

  POSIX Threads
     In applications that use the POSIX threads API  rather  than
     the   Solaris   threads   API  (  applications  linked  with
     -lpthread, whether or not linked with -lthread), a  call  to
     fork() is like a call to  fork1(), which replicates only the
     calling thread.
There is no call that forks a child with all
     threads and LWPs duplicated in the child.

     Note that if a program is  linked  with  both  libraries  (-
     lthread  and  -lpthread),  the POSIX semantic of fork() pre-
     vails.

最佳答案

查看完整内容

[ 本帖最后由 timespace 于 2009-4-16 22:51 编辑 ]

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
2 [报告]
发表于 2009-04-16 17:25 |只看该作者
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/wait.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int nowait = 0;

void* thFork(void*);
void pFiles();

/* gcc -g -O2 -Wall fork.c -o foo -lpthread -lrt */
int main()
{
    int ret = 0;
    pthread_t tid;
    struct timespec timeout;
    FILE* fp;
   
    pFiles("main");
    fp = fopen("my.txt", "w");
    assert(fp);
   
    assert(pthread_create(&tid, NULL, thFork, NULL) == 0);
   
    timeout.tv_sec = time(NULL) + 60;
    timeout.tv_nsec = 0;
    pthread_mutex_lock(&mutex);
    while (!nowait && ret != ETIMEDOUT) {
        ret = pthread_cond_timedwait(&cond, &mutex, &timeout);
    }
    pthread_mutex_unlock(&mutex);
   
    fprintf(stdout, "Main is done\n");
    fclose(fp);
   
    return 0;
}

void pFiles(char* prefix)
{
    FILE* fp;
    char cmd[64];
    char buf[1024];
   
    fprintf(stdout, "%s:\n", prefix);
    sprintf(cmd, "pfiles %ld", getpid());
    fp = popen(cmd, "r");
    assert(fp);
    while (fgets(buf, sizeof(buf), fp) != NULL) {
        fputs(buf, stdout);
    }
    pclose(fp);
}

void* thFork(void* args)
{
    struct timespec rqtm;
    int status;
    pid_t pid;
   
    rqtm.tv_sec = 3;
    rqtm.tv_nsec = 0;
    pthread_detach(pthread_self());
   
    pFiles("thFork");
    pid = fork();
    if (pid == 0) {
        nanosleep(&rqtm, NULL);
        pFiles("child");
        exit(0);
    } else if (pid < 0) {
        perror("fork");
        assert(0);
    }
    wait(&status);
   
    pthread_mutex_lock(&mutex);
    nowait = 1;
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);
    fprintf(stdout, "thFork is done\n");
   
    return NULL;
}

  1. -bash-3.00$ uname -a
  2. SunOS v440test-2 5.10 Generic_118833-36 sun4u sparc SUNW,Sun-Fire-V440
  3. -bash-3.00$ gcc -g -O2 -Wall fork.c -o foo -lpthread -lrt
  4. -bash-3.00$ ./foo
  5. main1:
  6. 1042:   ./foo
  7.   Current rlimit: 256 file descriptors
  8.    0: S_IFCHR mode:0620 dev:336,0 ino:12582946 uid:1010 gid:7 rdev:24,15
  9.       O_RDWR|O_NOCTTY|O_LARGEFILE
  10.       /devices/pseudo/pts@0:15
  11.    1: S_IFCHR mode:0620 dev:336,0 ino:12582946 uid:1010 gid:7 rdev:24,15
  12.       O_RDWR|O_NOCTTY|O_LARGEFILE
  13.       /devices/pseudo/pts@0:15
  14.    2: S_IFCHR mode:0620 dev:336,0 ino:12582946 uid:1010 gid:7 rdev:24,15
  15.       O_RDWR|O_NOCTTY|O_LARGEFILE
  16.       /devices/pseudo/pts@0:15
  17.    3: S_IFIFO mode:0000 dev:344,0 ino:30884122 uid:1010 gid:101 size:0
  18.       O_RDWR
  19. main2:
  20. 1042:   ./foo
  21.   Current rlimit: 256 file descriptors
  22.    0: S_IFCHR mode:0620 dev:336,0 ino:12582946 uid:1010 gid:7 rdev:24,15
  23.       O_RDWR|O_NOCTTY|O_LARGEFILE
  24.       /devices/pseudo/pts@0:15
  25.    1: S_IFCHR mode:0620 dev:336,0 ino:12582946 uid:1010 gid:7 rdev:24,15
  26.       O_RDWR|O_NOCTTY|O_LARGEFILE
  27.       /devices/pseudo/pts@0:15
  28.    2: S_IFCHR mode:0620 dev:336,0 ino:12582946 uid:1010 gid:7 rdev:24,15
  29.       O_RDWR|O_NOCTTY|O_LARGEFILE
  30.       /devices/pseudo/pts@0:15
  31.    3: S_IFREG mode:0644 dev:32,39 ino:72743 uid:1010 gid:101 size:0
  32.       O_WRONLY|O_CREAT|O_TRUNC
  33.       /export/home1/lbs/my.txt
  34.    4: S_IFIFO mode:0000 dev:344,0 ino:30884123 uid:1010 gid:101 size:0
  35.       O_RDWR
  36. thFork:
  37. 1042:   ./foo
  38.   Current rlimit: 256 file descriptors
  39.    0: S_IFCHR mode:0620 dev:336,0 ino:12582946 uid:1010 gid:7 rdev:24,15
  40.       O_RDWR|O_NOCTTY|O_LARGEFILE
  41.       /devices/pseudo/pts@0:15
  42.    1: S_IFCHR mode:0620 dev:336,0 ino:12582946 uid:1010 gid:7 rdev:24,15
  43.       O_RDWR|O_NOCTTY|O_LARGEFILE
  44.       /devices/pseudo/pts@0:15
  45.    2: S_IFCHR mode:0620 dev:336,0 ino:12582946 uid:1010 gid:7 rdev:24,15
  46.       O_RDWR|O_NOCTTY|O_LARGEFILE
  47.       /devices/pseudo/pts@0:15
  48.    3: S_IFREG mode:0644 dev:32,39 ino:72743 uid:1010 gid:101 size:0
  49.       O_WRONLY|O_CREAT|O_TRUNC
  50.       /export/home1/lbs/my.txt
  51.    4: S_IFIFO mode:0000 dev:344,0 ino:30884124 uid:1010 gid:101 size:0
  52.       O_RDWR
  53. child:
  54. 1049:   ./foo
  55.   Current rlimit: 256 file descriptors
  56.    0: S_IFCHR mode:0620 dev:336,0 ino:12582946 uid:1010 gid:7 rdev:24,15
  57.       O_RDWR|O_NOCTTY|O_LARGEFILE
  58.       /devices/pseudo/pts@0:15
  59.    1: S_IFCHR mode:0620 dev:336,0 ino:12582946 uid:1010 gid:7 rdev:24,15
  60.       O_RDWR|O_NOCTTY|O_LARGEFILE
  61.       /devices/pseudo/pts@0:15
  62.    2: S_IFCHR mode:0620 dev:336,0 ino:12582946 uid:1010 gid:7 rdev:24,15
  63.       O_RDWR|O_NOCTTY|O_LARGEFILE
  64.       /devices/pseudo/pts@0:15
  65.    3: S_IFREG mode:0644 dev:32,39 ino:72743 uid:1010 gid:101 size:0
  66.       O_WRONLY|O_CREAT|O_TRUNC
  67.       /export/home1/lbs/my.txt
  68.    4: S_IFIFO mode:0000 dev:344,0 ino:30884132 uid:1010 gid:101 size:0
  69.       O_RDWR
  70. thFork is done
  71. Main is done
复制代码

[ 本帖最后由 timespace 于 2009-4-16 22:51 编辑 ]

论坛徽章:
5
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:53:172015亚冠之水原三星
日期:2015-06-02 16:34:202015年亚冠纪念徽章
日期:2015-10-19 18:13:37程序设计版块每日发帖之星
日期:2015-11-08 06:20:00
3 [报告]
发表于 2009-04-16 20:33 |只看该作者
高级货 solaris 没玩过

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
4 [报告]
发表于 2009-04-16 20:59 |只看该作者

回复 #1 spiritX 的帖子

亲自写个代码就一目了然了。POSIX thread虽然要求fork仅复制calling thread,但是已经存在的多个线程共享的进程资源依然会到child process,比如信号量,互斥锁,文件描述符等等,所以清理工作变得很重要。看看下面这个函数的manual:
#include <pthread.h>
int pthread_atfork(void (*prepare)(void), void (*parent)(void),
       void (*child)(void));

论坛徽章:
0
5 [报告]
发表于 2009-04-17 13:38 |只看该作者
原帖由 timespace 于 2009-4-16 20:59 发表
亲自写个代码就一目了然了。POSIX thread虽然要求fork仅复制calling thread,但是已经存在的多个线程共享的进程资源依然会到child process,比如信号量,互斥锁,文件描述符等等,所以清理工作变得很重要。看看下 ...


那就是会被复制了 ?
你写的代码我没怎么细看,谢谢!

论坛徽章:
0
6 [报告]
发表于 2009-04-17 16:32 |只看该作者
man atfork
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP