11 / 11 / 0
Регистрация: 04.11.2012
Сообщений: 127

С++ под Linux, процессы fork() и каналы

30.05.2013, 09:31. Показов 5224. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вот такая штука... Нужно, так сказать, организовать общение между процессами через полудуплексный неименованный канал =)
Научился передавать между процессами одно чилсо... Но не получается передать массив =( Вот что делаю, когда передаю одно число:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int fd[2];
    char s[100];
    if(pipe(fd)<0)
    {
        printf("Не удалось создать кaнал!");
        return 0;
    }
    if(fork()==0)
    {
        entry_period(A,B);
        write(fd[1],&A,sizeof(int));
        write(fd[1],&B,sizeof(int));
        return 1;
    }
    read(fd[0],&A,sizeof(int));
    read(fd[0],&B,sizeof(int));
    wait(0);
функция entry_period:
C++
1
2
3
4
5
void entry_period(int &A, int &B)
{
    printf("Введите промежуток од А до B: ");
    scanf("%d %d", &A,&B);
}
Пытался записывать в канал по одно му введенному числу и потом считывать... Но не получается... Вот что делал:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
printf("\nВведите колличество С-элементов ");
    scanf("%d",&c);
    if(fork()==0)
    {
        
        //C=input_C_elements(c,A,B,amount);
        //write(fd[1],&amount,sizeof(int));
        C=new int[c];
        printf("\nВведите С-элементы:\n");
        for(int i=0;i<c;i++)
        {
            printf("Введите %d С-элемент ", i+1);
            scanf("%d",&C[i]);  
            write(fd[1],&C[i],sizeof(int));
            if(C[i]>=A && C[i]<=B)
            {
                amount++;
            }
        }
        write(fd[1],&amount,sizeof(int));
        return 1;
    }
    read(fd[0],&amount,sizeof(int));
    for(int i=0;i<amount;i++)
    {
        read(fd[0],&C[i],sizeof(int));
    }
Но это не работает =( Где я ошибся?... подскажите пожалуйста, буду за любой ответ благодарен =)
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
30.05.2013, 09:31
Ответы с готовыми решениями:

Fork() процессы
Здравствуйте, Помогите please объяснить программу, что она выполняет (Linux) main() { int n; for (n=0;n&lt;10;n++) ...

Убить все процессы, fork()
Не могу понять как убить все процессы после того как условие в if становится истинным //start child processes //int status = 0; ...

Процессы и каналы
Привет. Есть задание Всё понятно, кроме того, что выделено жирным, примерно понимание есть, но как реализовать как - не понимаю. ...

21
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
30.05.2013, 09:53
Во write как минимум.

C++
1
2
3
4
5
6
int value;
int array[size];
 
//fd - file descriptor. В Вашем случае fd[0]
write(fd, value, sizeof(int));
write(fd, array, sizeof(array) /*size * sizeof(int)*/);
1
11 / 11 / 0
Регистрация: 04.11.2012
Сообщений: 127
30.05.2013, 11:04  [ТС]
Цитата Сообщение от stima Посмотреть сообщение
Во write как минимум.
Не совсем понял... как то так:
C++
1
2
3
4
5
6
7
8
9
if(fork()==0)
    {
        
        C=input_C_elements(c,A,B,amount);
        write(fd[1],&C,sizeof(C));
        return 1;
    }
read(fd[0],&C,sizeof(C));
    wait(0);
Функция input_C_elements:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int *input_C_elements(int c, int A, int B, int amount)
{
    int *C;
    C=new int[c];
    printf("\nВведите С-элементы:\n");
    for(int i=0;i<c;i++)
    {
        printf("Введите %d С-элемент ", i+1);
        scanf("%d",&C[i]);
        if(C[i]>=A && C[i]<=B)
        {
            amount++;
        }
    }
    return C;
}
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
30.05.2013, 11:07
C++
1
2
C=input_C_elements(c,A,B,amount);
        write(fd[1],&C,sizeof(C)); // смотреть сюда. думайте что не так
Наводящий вопрос - подсказка. Как вы выведите в stdout переменную и массив строк?
1
11 / 11 / 0
Регистрация: 04.11.2012
Сообщений: 127
30.05.2013, 14:05  [ТС]
Цитата Сообщение от stima Посмотреть сообщение
write(fd[1],&C,sizeof(C));
Не совсем понял... о какой переменной идет речь?
А вот второе я не знаю... Я хотел записать в fd[1] информацию и из fd[0] потом ее считывать, &С это, как я пологаю, указатель на начала моего массива и sizeof(C) это размер, который я буду записывать... Что не так? =)
ну а считываю я так:
C++
1
read(fd[0],&C,sizeof(C));
Добавлено через 34 минуты
Вот еще такой вопрос... Почему в функции:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int *input_C_elements(int c, int A, int B, int amount)
{
    int *C;
    C=new int[c];
    printf("\nВведите С-элементы:\n");
    for(int i=0;i<c;i++)
    {
        printf("Введите %d С-элемент ", i+1);
        scanf("%d",&C[i]);
        if(C[i]>=A && C[i]<=B)
        {
            amount++;
        }
    }
    printf("\n\n\n %d \n\n\n", amount);
    return C;
}
переменная amount выдает то значение, что надо, но когда я в main пишу:
C++
1
2
C=input_C_elements(c,A,B,amount);
        printf("\n\n\n %d \n\n\n", amount);
amount не выдает то, что было в функции?...
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
30.05.2013, 14:11
О да Вы оказывается не знаете примитивов, а взялись за пайпы. Разговор бессмысленен пока вы не прочитаете что такое:
1. Переменная.
2. Указатель.
3. Массив.
4. Функция.
5. Передача переменных/массивов в функцию (по значению, указателю, ссылке)
1
11 / 11 / 0
Регистрация: 04.11.2012
Сообщений: 127
30.05.2013, 14:16  [ТС]
Цитата Сообщение от stima Посмотреть сообщение
О да Вы оказывается не знаете примитивов, а взялись за пайпы. Разговор бессмысленен пока вы не прочитаете что такое:
1. Переменная.
2. Указатель.
3. Массив.
4. Функция.
5. Передача переменных/массивов в функцию (по значению, указателю, ссылке)
Давно не программировал на С++, поэтому так получается... Это в роле оправдания моего =)
Что именно я не так сделал в коде? =)
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
30.05.2013, 14:25
Почитайте, это долго расписывать. Тем более без данных примитивов вы вряд ли сможете что-то разработать дальше.
1
11 / 11 / 0
Регистрация: 04.11.2012
Сообщений: 127
30.05.2013, 14:58  [ТС]
Цитата Сообщение от stima Посмотреть сообщение
Почитайте, это долго расписывать. Тем более без данных примитивов вы вряд ли сможете что-то разработать дальше.
Эх... привет бессонным ночи =))

Добавлено через 5 минут
Если я хочу сделать указатель на массив array я буду делать так:
//опустим выделение памяти и тп.
int *ptr;
ptr = array; или ptr = &array[0];
Я же тоже самое делаю...
В функции есть массив С, его я возвращаю и в main у меня есть указатель *C и собственно C=input_C_elements(c,A,B,amount); это тоже самое что и ptr = array;.... что не так? =)
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
30.05.2013, 15:16
1. то что функция input_C_elements, возвращает указатель. В Вашем случае указатель на первый элемент массива.
А функция write принимает указатель на область данных.

Это то что Вы написали.
C++
1
write(fd[1],&C,sizeof(C));
Расшифровываю:
Запиши данные в файловый дискриптор fd[1] из переменной С размером с переменную С.
Так вот переменная С это УКАЗАТЕЛЬ и &c это взятие адреса указателя, а sizeof(C) это sizeof(void*)

2. Функция input_C_elements принимает ПО ЗНАЧЕНИЮ amount.

Советую все таки прочитать, то что я написал.
1
11 / 11 / 0
Регистрация: 04.11.2012
Сообщений: 127
30.05.2013, 16:41  [ТС]
Блин.... Ну нифига не выходит...
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
30.05.2013, 17:49
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
 
#define PIPE_FD_READ  0
#define PIPE_FD_WRITE 1
 
int main()
{
    int pipe_fd[2];
 
    if (pipe(pipe_fd) == -1)
    {
        perror("Pipe error: ");
        exit(EXIT_FAILURE);
    }
 
    int pid = fork();
    if (pid == -1)
    {
        perror("Fork error: ");
        exit(EXIT_FAILURE);
    }
    
    if (pid == 0)
    {
        close(pipe_fd[PIPE_FD_WRITE]);
 
        int size = 0;
        read(pipe_fd[PIPE_FD_READ], &size, sizeof(int));
 
        int *array = (int*)malloc(size * sizeof(int));
        read(pipe_fd[PIPE_FD_READ], array, size * sizeof(int));
 
        printf("\narray was resived: ");
 
        int last = size - 1;
        for (int i = 0; i < last; ++i)
            printf("%d ", array[i]);
        printf("%d\n", array[last]);
 
        free(array);
        
        exit(0);
    }
    else
    {
        close(pipe_fd[PIPE_FD_READ]);
 
        int size = 10;
        int *array = (int*)malloc(size * sizeof(int));
        
        printf("array was sended: ");
 
        srand(time(NULL));
        int last = size - 1;
        for (int i = 0; i < last; ++i)
        {
            array[i] = rand() % 100;
            printf("%d ", array[i]);
        }
        array[last] = rand() % 100;
        printf("%d\n", array[last]);
 
        write(pipe_fd[PIPE_FD_WRITE], &size, sizeof(int));
        write(pipe_fd[PIPE_FD_WRITE], array, size * sizeof(int));
        free(array);    
 
        exit(0);
    }
 
    return 0;
}
p.s. И все таки я советую вам почитать основы.
1
11 / 11 / 0
Регистрация: 04.11.2012
Сообщений: 127
30.05.2013, 20:17  [ТС]
Но я так и записываю в канал... но ничего не пишется:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if(fork()==0)
    {
        C=new int[c];
        printf("\nВведите С-элементы:\n");
        for(int i=0;i<c;i++)
        {
            printf("Введите %d С-элемент ", i+1);
            scanf("%d",&C[i]);
            if(C[i]>=A && C[i]<=B)
            {
                amount++;
            }
        }   
        //C=input_C_elements(c,A,B,amount);
        write(fd[1],&amount,sizeof(int));
        write(fd[1],C,sizeof(int)*amount);
        return 1;
    }
    //read(fd[0],&amount,sizeof(int));
    read(fd[0],&amount,sizeof(int));
    read(fd[0],C,sizeof(int));
    wait(0);
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
30.05.2013, 22:12
Ну во первых подумайте над этим.
Цитата Сообщение от Apelsin199 Посмотреть сообщение
read(fd[0],C,sizeof(int));
Во вторых полный код в студию.
1
11 / 11 / 0
Регистрация: 04.11.2012
Сообщений: 127
31.05.2013, 06:36  [ТС]
Цитата Сообщение от stima Посмотреть сообщение
Во вторых полный код в студию.
Позже кину весь код, не знаю правда, чем это поможет )
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
31.05.2013, 12:26
Хватит кадра стека. Да поможет.
1
11 / 11 / 0
Регистрация: 04.11.2012
Сообщений: 127
31.05.2013, 12:35  [ТС]
Вот такая штука в общем... Вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include<clocale>
#include<stdio.h>
#include <unistd.h>
#include <string>
#include <unistd.h>
#include <iostream>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
 
 
//Функция введения промежутка
void entry_period(int &A, int &B)
{
    printf("Введите промежуток од А до B: ");
    scanf("%d %d", &A,&B);
}
 
//функция ввода С-элементов
int *input_C_elements(int c, int A, int B, int amount)
{
    int *C;
    C=new int[c];
    printf("\nВведите С-элементы:\n");
    for(int i=0;i<c;i++)
    {
        printf("Введите %d С-элемент ", i+1);
        scanf("%d",&C[i]);
        if(C[i]>=A && C[i]<=B)
        {
            amount++;
        }
    }
    printf("\n\n\n %d \n\n\n", amount);
    return C;
}
 
//Функция вывода исключений
void withdrawal_exemptions(int A, int B, int *C, int c)
{
    printf("\nВведите элементы массива удовлетворяющие следующим свойствам:");
    printf("\n1. Элементы массива должны находится в промежудке от %d до %d", A,B);
    printf("\n2. Элеменами массива не могут быть следующие числа: ");
    for(int i=0;i<c;i++)
    {
        printf("%d ",C[i]);
    }
}
 
//ввод заключительного массива
int *input_array(int A, int B, int *C, int c, int amount)
{
    int buf;
    printf("\nРазмер массива = %d", (B-A-amount));
    int *mas;
    mas=new int[B-A-amount];
    for(int i=0;i<(B-A-amount);i++)
    {
        printf("\nВведите %d элемент массива ",i+1);
        scanf("%d",&buf);
        for(int j=0;j<c;j++)
        {
            if(buf==C[j])
            {
                printf("\nВведенное число равно запрещенному числу! а именно %d", C[j]);
                printf("\n****************Повторите ввод!****************\n");
                if(i==-1)
                {
                    i=-1;
                }
                else
                {
                    i--;
                }
                break;
            }
        }
        if(buf<A || buf>B)
        {
            printf("\nВведенное число не входит в промежуток от %d до %d", A,B);
            printf("\n****************Повторите ввод!****************\n");
            i--;
        }
        else
        {
            mas[i]=buf;
        }
    }
    printf("\n\n*********************Полученный массив:*********************\n");
    for(int i=0;i<(B-A-amount);i++)
    {
        printf("%d ", mas[i]);
    }
    return mas;
}
 
//нахождение среднего арифметического
int find_arithmetic_mean(int A, int B, int amount, int *mas)
{
    float sr=0;
    printf("\n\n*************Нахождение среднего арифмитического************\n");
    for(int i=0;i<(B-A-amount);i++)
    {
        sr=sr+mas[i];
    }
    sr=sr/(B-A-amount);
    return sr;
}
 
int main()
{
    setlocale(LC_ALL,"rus");
    int A=0,B=0;
    int c;
    int *C;
    int amount=0;
    int fd[2];
    char s[100];
    if(pipe(fd)<0)
    {
        printf("Не удалось создать кaнал!");
        return 0;
    }
    if(fork()==0)
    {
        entry_period(A,B);
        write(fd[1],&A,sizeof(int));
        write(fd[1],&B,sizeof(int));
        return 1;
    }
    read(fd[0],&A,sizeof(int));
    read(fd[0],&B,sizeof(int));
    wait(0);
    printf("\nВведите колличество С-элементов ");
    scanf("%d",&c);
    if(fork()==0)
    {
        C=new int[c];
        printf("\nВведите С-элементы:\n");
        for(int i=0;i<c;i++)
        {
            printf("Введите %d С-элемент ", i+1);
            scanf("%d",&C[i]);
            if(C[i]>=A && C[i]<=B)
            {
                amount++;
            }
        }   
        //C=input_C_elements(c,A,B,amount);
        write(fd[1],&amount,sizeof(int));
        //write(fd[1],C,sizeof(int)*amount);
        return 1;
    }
    //read(fd[0],&amount,sizeof(int));
    read(fd[0],&amount,sizeof(int));
    //read(fd[0],C,sizeof(int)*amount);
    wait(0);
    if((B-A)<=amount)
    {
        printf("Аварийный выход!\n");
        return 0;
    }
    int *mas;
    if(fork()==0)
    {
        withdrawal_exemptions(A,B,C,c);
        return 0;
    }
    wait(0);
    if(fork()==0)
    {
        mas=input_array(A,B,C,c,amount);
        return 0;
    }
    wait(0);
    float sr;
    sr=find_arithmetic_mean(A,B,amount,mas);
    printf("\nСреднее арифмитическое равно: %f\n\n", sr);
 
    close(fd[0]); close(fd[1]);
    return 0;
}
Он само собой еще не доделан.... Вот сама задача:
Сформировать массив, элементами которого являются целые числа больше А,
меньше В и не равные С1, С2, ... Сn. Найти среднее арифметическое элементов
полученного массива. Входные данные: число А, число Б, произвольное
количество чисел С1, С2, ... Сn. Использовать не менее четырех процессов для
решения задачи.

Сегодня общался с преподователем, она сказала, что не знает почему у меня не пишется или не читается и посоветовала писать в канал поэлементно, этим я и займусь, НО я очень хочу разобраться, почему с массивом такая у меня проблема...
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
31.05.2013, 13:01
Цитата Сообщение от Apelsin199 Посмотреть сообщение
почему у меня не пишется или не читается и посоветовала писать в канал поэлементно,
)), найдите препода с бородой.

Уточняющий вопрос. Использовать потоки или процессы? Дело в том что это разные вещи, с точки зрения программирования в общем, просто linux имеет свое мнение и релизацию данных вещей.

Какая цель "не менее четырех процессов для"? Распараллелить задачу? Или Именно научиться использовать IPC (межпроцессорное взаимодействие)?

Добавлено через 19 минут
п.с. И определитесь на каком языке Вы пишите. Си или С++
1
11 / 11 / 0
Регистрация: 04.11.2012
Сообщений: 127
31.05.2013, 14:20  [ТС]
Цитата Сообщение от stima Посмотреть сообщение
п.с. И определитесь на каком языке Вы пишите. Си или С++
Дело в том, что мне нравится писать смешено, я вижу в этом плюсы =) Но вы как мой "гуру" в этой лабе, если скажите, буду писать на конкретном языке =))
А на счет потоков или процессов... Я понял задачу так... Есть программа, к примеру как моя, написанная на СИ/С++ и всю программу будет выполнять родительский процесс, но я разбиваю программу на 4 fork(), таким образом имею дочерние процессы (выполнил условие "не менее четырех процессов для"). Но, так как, по завершению дочернего процесса, другой начавшийся дочерний процесс или даже тот же родительский процесс не будут знать о том, что произошло в выполнившемся дочернем процессе... Я имею ввиду вот что... Если я в родительском процессе создам переменную m и скажу что она равно нулю, а затем в дочернем процессе присвою переменной m значение 5, то по окончанию дочернего процесса, в родительском переменная m останется быть равна 0... Поэтому нужны каналы, чтоб сообщить о изменениях и тп. Я правильно рассуждаю? =)
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
31.05.2013, 17:00
Нет вы не поняли. В Linux подобных OS потоки реализованы через процессы. И запуск 4 потоков, это запуск 4 процессов.

В программировании под процессом понимают выполнение программы с использованием отдельной выделенной области памяти. В то время как поток может использовать ту же память что и породивший его процесс. Как-то так.

Так вот какая академическая задача стоит? Научиться использовать межпроцессорное взаимодействие или уметь распаралеливать задачу?
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
31.05.2013, 17:00
Помогаю со студенческими работами здесь

Процессы и именованные каналы
Подскажите пожалуйста, если можно примером кода или его наброском. Так же можно сбросить по возможности сайты с примерами. Нужно с...

Принцип работы отладчика в Linux и fork()
Добрый день всем! Вопрос к знатокам Линукс и UNIX-подобных систем. Дайте пожалуйста ссылки, где можно кратко и доступно прочитать о...

Клиент-сервер TCP для Linux с fork
Помогите написать клиент серверную программу TCP для Linux с fork. Демонстрация должна быть такая: к серверу подключается несколько...

Именованные каналы в Linux
Прошу помощи с именованными каналами . Нужно передать данные от 1-го процесса в 2-ой . В 1-ом процессе вводятся данные , а во 2-ом они...

Linux pipes(каналы)
#include &lt;string.h&gt; #include &lt;stdlib.h&gt; #include &lt;stdio.h&gt; #include &lt;unistd.h&gt; #define MAX_STRING_LENGTH 255 #define MAX_TOKS...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

Новые блоги и статьи
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru